1 | /*************************************** 2 | 3 | Protocol mirror module (pw). Whois protocol. 4 | 5 | Status: NOT REVUED, NOT TESTED 6 | 7 | ******************/ /****************** 8 | Filename : protocol_mirror.c 9 | Author : andrei 10 | OSs Tested : Solaris 11 | ******************/ /****************** 12 | Copyright (c) 1999 RIPE NCC 13 | 14 | All Rights Reserved 15 | 16 | Permission to use, copy, modify, and distribute this software and its 17 | documentation for any purpose and without fee is hereby granted, 18 | provided that the above copyright notice appear in all copies and that 19 | both that copyright notice and this permission notice appear in 20 | supporting documentation, and that the name of the author not be 21 | used in advertising or publicity pertaining to distribution of the 22 | software without specific, written prior permission. 23 | 24 | THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 25 | ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS; IN NO EVENT SHALL 26 | AUTHOR BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY 27 | DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN 28 | AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 29 | OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 30 | ***************************************/ 31 | #include <stdio.h> 32 | #include <glib.h> 33 | 34 | #include "protocol_mirror.h" 35 | #include "mysql_driver.h" 36 | #include "constants.h" 37 | 38 | //#include "access_control.h" 39 | #include "socket.h" 40 | #include "stubs.h" 41 | #include "ud.h" 42 | #include "ta.h" 43 | 44 | #include "ca_configFns.h" 45 | #include "ca_dictSyms.h" 46 | #include "ca_macros.h" 47 | #include "ca_srcAttribs.h" 48 | 49 | 50 | 51 | #define MIN_ARG_LENGTH 6 52 | #define NRTM_DELIM "-:" 53 | /* 54 | * parses input and fills nrtm_q_t structure 55 | * 56 | * Returns: 57 | * -1 in case of garbage 58 | * 0 in case of valid -g 59 | * 1 in case of -q sources 60 | * 61 | */ 62 | static int parse_request(char *input, nrtm_q_t *nrtm_q) 63 | { 64 | char *ptr=input; 65 | char *token; 66 | char **tokens; 67 | char **tokens2; 68 | int res=0; 69 | 70 | // return(-1); 71 | 72 | if(strlen(input)<MIN_ARG_LENGTH) return(-1); 73 | g_strchug(input); 74 | res=strncmp(input, "-g", 2); 75 | if(res!=0) { 76 | /* may be this is -q source query */ 77 | res=strncmp(input, "-q", 2); 78 | if(res!=0)return(-1); 79 | ptr+=2; 80 | g_strchug(ptr); 81 | res=strncmp(ptr, "sources", 7); 82 | if(res!=0)return(-1); 83 | ptr+=7; 84 | g_strchug(ptr); 85 | token=ptr; 86 | if ((*token=='\0') || (*token=='\n'))nrtm_q->source=NULL; 87 | else { 88 | ptr=index(token, ' '); 89 | if (ptr) nrtm_q->source=g_strndup(token, (ptr-token)); 90 | else nrtm_q->source=g_strdup(token); 91 | } 92 | return(1); 93 | } 94 | 95 | /* this is -q query */ 96 | ptr+=2; 97 | 98 | 99 | g_strchug(ptr); 100 | g_strdelimit(ptr, NRTM_DELIM, ':'); 101 | tokens=g_strsplit(ptr, ":", 4); 102 | if(tokens==NULL) return(-1); 103 | 104 | if(tokens[0]) { 105 | /* first token is source name */ 106 | nrtm_q->source=g_strdup(tokens[0]); 107 | if(tokens[1]) { 108 | /* second token is version number */ 109 | nrtm_q->version=atoi(tokens[1]); 110 | if(tokens[2]) { 111 | /* this is first serial */ 112 | nrtm_q->first=atol(tokens[2]); 113 | if(tokens[3]) { 114 | /* this is last serial */ 115 | nrtm_q->last=atol(tokens[3]); 116 | } else res=-1; 117 | } else res=-1; 118 | } else res=-1; 119 | } else res=-1; 120 | g_strfreev(tokens); 121 | 122 | return(res); 123 | } 124 | 125 | 126 | /* PM_interact() */ 127 | /*++++++++++++++++++++++++++++++++++++++ 128 | Interact with the client. 129 | 130 | int sock Socket that client is connected to. 131 | 132 | More: 133 | +html+ <PRE> 134 | Authors: 135 | ottrey 136 | andrei 137 | 138 | +html+ </PRE><DL COMPACT> 139 | +html+ <DT>Online References: 140 | +html+ <DD><UL> 141 | +html+ </UL></DL> 142 | 143 | ++++++++++++++++++++++++++++++++++++++*/ 144 | void PM_interact(int sock) { 145 | char input[MAX_INPUT_SIZE]; 146 | ca_dbSource_t *source_hdl; 147 | int read_result; 148 | int parse_result; 149 | ip_addr_t address; 150 | 151 | 152 | 153 | char *hostaddress=NULL; 154 | // acl_st acl_rip, acl_eip; 155 | 156 | sk_conn_st condat; 157 | nrtm_q_t nrtm_q; 158 | long current_serial; 159 | long oldest_serial; 160 | 161 | char *object; 162 | int operation; 163 | char buff[STR_S]; 164 | 165 | const char *db_host; 166 | int db_port; 167 | const char *db_name; 168 | const char *db_user; 169 | const char *db_pswd; 170 | 171 | GString *gbuff; 172 | 173 | SQ_connection_t *sql_connection; 174 | 175 | /* make a record for thread accounting */ 176 | TA_add(sock, "nrtm_srv"); 177 | 178 | 179 | /* Get the IP of the client */ 180 | hostaddress = SK_getpeername(sock); 181 | printf("SK address: %s\n", hostaddress); 182 | 183 | /* initialise the connection structure */ 184 | memset( &condat, 0, sizeof(sk_conn_st)); 185 | /* set the connection data: both rIP and eIP to real IP */ 186 | condat.sock = sock; 187 | condat.ip = hostaddress; 188 | SK_getpeerip(sock, &(condat.rIP)); 189 | memcpy( &(condat.eIP), &(condat.rIP), sizeof(ip_addr_t)); 190 | 191 | 192 | /* Read input */ 193 | read_result = SK_cd_gets(&(condat), input, MAX_INPUT_SIZE); 194 | 195 | /* read_result < 0 is an error and connection should be closed */ 196 | if (read_result < 0 ) { 197 | /* log the fact, rtc was set */ 198 | //not yet, SK_... returns arb number return; 199 | } 200 | 201 | parse_result = parse_request(input, &nrtm_q); 202 | if (parse_result < 0 ) { 203 | fprintf(stderr, "Garbage received: %s\n", input); 204 | /* log the fact and exit */ 205 | /* Free the hostaddress */ 206 | SK_cd_close(&(condat)); 207 | free(hostaddress); 208 | free(nrtm_q.source); 209 | return; 210 | } 211 | if (parse_result == 1 ) { 212 | 213 | fprintf(stderr, "-q sources\n"); 214 | gbuff=PM_get_nrtm_sources(&(condat.rIP), nrtm_q.source); 215 | SK_cd_puts(&condat, gbuff->str); 216 | /* Free allocated memory */ 217 | g_string_free(gbuff, TRUE); 218 | free(hostaddress); 219 | free(nrtm_q.source); 220 | SK_cd_close(&(condat)); 221 | return; 222 | } 223 | 224 | source_hdl = ca_get_SourceHandleByName(nrtm_q.source); 225 | if (source_hdl == NULL){ 226 | sprintf(buff, "\n%%ERROR 6: Unknown source\n\n"); 227 | SK_cd_puts(&condat, buff); 228 | free(hostaddress); 229 | free(nrtm_q.source); 230 | SK_cd_close(&(condat)); 231 | return; 232 | } 233 | 234 | /* check if the client is authorized to mirror */ 235 | SK_getpeerip(sock, &address); 236 | if(!AA_can_mirror(&address, nrtm_q.source)){ 237 | sprintf(buff, "\n%%ERROR 5: You are not authorized to mirror the database\n\n"); 238 | SK_cd_puts(&condat, buff); 239 | free(hostaddress); 240 | free(nrtm_q.source); 241 | SK_cd_close(&(condat)); 242 | return; 243 | } 244 | 245 | 246 | 247 | /* get database */ 248 | /* db_name=CO_get_database(); */ 249 | db_name = ca_get_srcdbname(source_hdl); 250 | 251 | /* get database host*/ 252 | /* db_host=CO_get_host();*/ 253 | db_host = ca_get_srcdbmachine(source_hdl); 254 | /* get database port*/ 255 | /* db_port=CO_get_database_port();*/ 256 | db_port = ca_get_srcdbport(source_hdl); 257 | /* get database user*/ 258 | /* db_user=CO_get_user(); */ 259 | db_user = ca_get_srcdbuser(source_hdl); 260 | /* get database password*/ 261 | /* db_pswd=CO_get_password(); */ 262 | db_pswd = ca_get_srcdbpassword(source_hdl); 263 | 264 | fprintf(stderr, "D: Making SQL connection to %s@%s ...", db_name, db_host); 265 | sql_connection = SQ_get_connection(db_host, db_port,db_name, db_user, db_pswd); 266 | if(!sql_connection) { 267 | fprintf(stderr, "E: ERROR: no SQL connection\n"); 268 | return; 269 | } 270 | fprintf(stderr, "OK\n"); 271 | 272 | /* free copies of the variables */ 273 | free(db_host); 274 | free(db_name); 275 | free(db_user); 276 | free(db_pswd); 277 | 278 | current_serial=PM_get_current_serial(sql_connection); 279 | oldest_serial=PM_get_oldest_serial(sql_connection); 280 | 281 | if((current_serial==-1) || (oldest_serial==-1)) { 282 | fprintf(stderr, "E: ERROR: cannot get serial #\n"); 283 | /* Free the hostaddress */ 284 | SK_cd_close(&(condat)); 285 | free(hostaddress); 286 | free(nrtm_q.source); 287 | return; 288 | } 289 | 290 | /* zero indicates that LAST keyword has been used */ 291 | if(nrtm_q.last==0)nrtm_q.last=current_serial; 292 | 293 | 294 | if((nrtm_q.first>nrtm_q.last) || (nrtm_q.first<oldest_serial) || (nrtm_q.last>current_serial)) { 295 | if(nrtm_q.first<oldest_serial) nrtm_q.last=oldest_serial-1; 296 | if(nrtm_q.last>current_serial) nrtm_q.first=current_serial+1; 297 | fprintf(stderr, "E: ERROR: invalid range\n"); 298 | /* write error message back to the client */ 299 | /* sprintf(buff, "%%ERROR:4: Invalid range: serial(s) %ld-%ld don't exist\n", nrtm_q.first, nrtm_q.last); */ 300 | sprintf(buff, "\n%%ERROR:4: Invalid range: Not within %ld-%ld\n\n", oldest_serial, current_serial); 301 | SK_cd_puts(&condat, buff); 302 | SK_cd_close(&(condat)); 303 | 304 | /* Free the hostaddress */ 305 | free(hostaddress); 306 | free(nrtm_q.source); 307 | return; 308 | } 309 | 310 | current_serial=nrtm_q.first; 311 | /* print banner */ 312 | 313 | sprintf(buff, "%%START Version:%d %s %ld-%ld\n", nrtm_q.version, nrtm_q.source, nrtm_q.first, nrtm_q.last); 314 | SK_cd_puts(&condat, buff); 315 | 316 | /* make a record for thread accounting */ 317 | TA_setactivity(buff); 318 | 319 | /* now start feeding client with data */ 320 | do { 321 | 322 | object=PM_get_serial_object(sql_connection, current_serial, &operation); 323 | if (operation == OP_ADD) SK_cd_puts(&condat, "\nADD\n\n"); 324 | else SK_cd_puts(&condat, "\nDEL\n\n"); 325 | 326 | SK_cd_puts(&condat, object); 327 | 328 | free(object); 329 | current_serial++; 330 | 331 | 332 | } /* do */ 333 | while((current_serial<=nrtm_q.last) && (condat.rtc == 0)); 334 | 335 | 336 | sprintf(buff, "\n%%END %s\n\n", nrtm_q.source); 337 | SK_cd_puts(&condat, buff); 338 | 339 | /* make a record for thread accounting */ 340 | TA_delete(); 341 | 342 | SK_cd_close(&(condat)); 343 | /* Free the hostaddress */ 344 | free(hostaddress); 345 | free(nrtm_q.source); 346 | 347 | 348 | 349 | } /* PM_interact() */