package net.websoup.wormscan; /* * This file is part of WormScan. * * WormScan is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ import java.net.InetAddress; import java.io.Serializable; import java.util.StringTokenizer; import net.websoup.wormscan.Attack; import net.websoup.wormscan.Program; import org.apache.oro.text.perl.Perl5Util; /** * Store everything we know about an attacking machine. * We will also use the Serialization mechanism for caching. * Copyright: Copyright (c) 2001-2004 Andriy Rozeluk * @author Andriy Rozeluk * @version 1.6.1 */ public class AttackSource implements Serializable { private static Perl5Util util; static { util = new Perl5Util(); } /* in case of updates to this class, don't screw up the DNS cache */ static final long serialVersionUID = -2973424726146112036L; /* count number of attacks by this host. Don't store in cache */ private transient int attackCount = 0; /* all resolved hostnames for this ip */ private String[] hostnames; /* reversed hostnames for sorting purposes */ private String[] hostnamesRev; /* ip address in String format */ private String ip; /* ip address as long */ private long ipAddress = 0; /* earliest attack by this ip. Don't store in cache */ private transient Attack firstAttack = null; /* latest attack by this ip. Don't store in cache */ private transient Attack lastAttack = null; public AttackSource(String ip) { this.ip = ip; attackCount = 0; convertIP(); } /** * Reverses a host name. For example, * www.websoup.net becomes * com.websoup.www */ private String reverseHostname( String input ){ if ( input.indexOf( "." ) < 0 ){ return input; } StringTokenizer st = new StringTokenizer( input, "." ); String[] tokens = new String[ st.countTokens() ]; for ( int i = 0; i < tokens.length; i++ ){ tokens[i] = st.nextToken(); } StringBuffer sb = new StringBuffer(); for ( int i = tokens.length - 1; i >= 0; i-- ){ sb.append( tokens[i] ); if ( i > 0 ){ sb.append( "." ); } } return sb.toString().toLowerCase(); } /** * Does this String consist of just digits + "." */ private static boolean verifyIPCharacters( String input ){ return util.match( "/^[0-9]{1,3}[.]{1,1}[0-9]{1,3}[.]{1,1}[0-9]{1,3}[.]{1,1}[0-9]{1,3}$/", input ); } /** * Convert an IP address to its 32-bit int version */ public void convertIP(){ if ( !verifyIPCharacters( ip ) ){ if ( Program.OUTPUT_LEVEL > 3 ) System.err.println( "Failed to parse IP address correctly (perhaps it's a hostname): " + ip ); this.ipAddress = -1; return; } StringTokenizer st = new StringTokenizer( ip, "." ); long ipAddress = 0; try { long token = Long.parseLong( st.nextToken() ); if ( token < 0 || token > 255 ){ throw new Exception( "Invalid IP address" ); } ipAddress = ( token << 24 ); token = Long.parseLong( st.nextToken() ); if ( token < 0 || token > 255 ){ throw new Exception( "Invalid IP address" ); } ipAddress += ( token << 16 ); token = Long.parseLong( st.nextToken() ); if ( token < 0 || token > 255 ){ throw new Exception( "Invalid IP address" ); } ipAddress += ( token << 8 ); token = Long.parseLong( st.nextToken() ); if ( token < 0 || token > 255 ){ throw new Exception( "Invalid IP address" ); } ipAddress += token; this.ipAddress = ipAddress; if ( Program.OUTPUT_LEVEL > 3 ) System.err.println( "IP address converted to long: " + ipAddress ); } catch ( Exception e ){ if ( Program.OUTPUT_LEVEL > 1 ) System.err.println( "Failed to parse IP address correctly (perhaps it's a hostname): " + ip ); this.ipAddress = -1; } } /** * Is this attack the last attack from this host? */ public boolean isLastAttack( Attack check ){ return check.equals( lastAttack ); } /** * Is this attack the first attack from this host? */ public boolean isFirstAttack( Attack check ){ return check.equals( firstAttack ); } /** * Returns the last attack from this host */ public Attack getLastAttack(){ return lastAttack; } /** * Returns the first attack from this host */ public Attack getFirstAttack(){ return firstAttack; } /** * Save firstAttack or lastAttack information, if applicable */ public void checkAttackDates( Attack check ){ if ( lastAttack == null || check.getDateOfAttack().after( lastAttack.getDateOfAttack() ) ) lastAttack = check; if ( firstAttack == null || check.getDateOfAttack().after( firstAttack.getDateOfAttack() ) ) firstAttack = check; } /** * Just what it says. Find out what the hostnames are. */ public void resolveHostnames(){ InetAddress[] source = null; try { source = InetAddress.getAllByName(ip); } catch ( java.net.UnknownHostException e ){ //what do you expect me to do? } if ( source != null && source.length > 0 ){ hostnames = new String[ source.length ]; for ( int i = 0; i < source.length; i++ ){ if ( ipAddress <= 0 ){ ip = source[i].getHostAddress(); convertIP(); } hostnames[i] = source[i].getHostName(); } if ( Program.OUTPUT_LEVEL > 3 ){ if (hostnames.length > 0){ System.out.println( ip + " resolved to " + hostnames[0] ); } else { System.out.println( "Could not resolve hostname for " + ip ); hostnames = new String[1]; hostnames[0] = ip; } } } else { hostnames = new String[1]; hostnames[0] = ip; } } /** * Returns all resolved hostnames for this host */ public String[] getAttackHostnames(){ return hostnames; } /** * Returns all resolved hostnames (reversed domains) for sorting */ public String[] getReversedHostnames(){ if (hostnamesRev == null){ if ( hostnames == null ){ return null; } hostnamesRev = new String[ hostnames.length ]; for( int i = 0; i < hostnames.length; i++ ){ hostnamesRev[i] = reverseHostname( hostnames[i] ); } } return hostnamesRev; } public boolean isHostnameUnresolved(){ if ( hostnames == null || hostnames.length < 1 ){ return true; } return hostnames[0].equals(ip); } public boolean isHostnameOnly(){ return (isHostnameUnresolved() && ipAddress <= 0); } /** * Returns 32-bit int version of IP address */ public long getIntegerIP(){ return ipAddress; } /** * Returns String version of IP address */ public String getAttackIP(){ return ip; } /** * Increment attack counter for this host */ public void addAttack(){ attackCount++; } /** * Return attack count for this host */ public int getAttackCount(){ return attackCount; } /** * Reset attack count for this host */ public void resetAttackCount(){ attackCount = 0; } }