package com.legind.swinedroid; import java.io.IOException; import java.io.UnsupportedEncodingException; import java.math.BigInteger; import java.net.InetAddress; import java.net.UnknownHostException; import org.xml.sax.SAXException; import android.app.Activity; import android.app.ProgressDialog; import android.content.Context; import android.content.DialogInterface; import android.content.Intent; import android.content.DialogInterface.OnCancelListener; import android.graphics.Color; import android.os.Bundle; import android.os.Handler; import android.os.Message; import android.text.ClipboardManager; import android.util.Log; import android.view.Gravity; import android.view.LayoutInflater; import android.view.Menu; import android.view.MenuItem; import android.view.ViewGroup; import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.RelativeLayout; import android.widget.TableLayout; import android.widget.TableRow; import android.widget.TextView; import android.widget.Toast; import android.widget.RelativeLayout.LayoutParams; import com.legind.Dialogs.ErrorMessageHandler; import com.legind.sqlite.AlertDbAdapter; import com.legind.sqlite.ServerDbAdapter; import com.legind.swinedroid.NetworkRunnable.NetworkRunnable; import com.legind.swinedroid.NetworkRunnable.NetworkRunnableRequires; import com.legind.swinedroid.xml.AlertXMLHandler; import com.legind.swinedroid.xml.XMLHandlerException; import com.legind.web.WebTransport.WebTransportException; public class AlertView extends Activity implements NetworkRunnableRequires{ private Long mRowId; private ProgressDialog pd; private ProgressDialog pdRDNS; private AlertXMLHandler mAlertXMLHandler; private ServerDbAdapter mDbHelper; private long mCid; private long mSid; private String mSigName; private InetAddress mIpSrc; private InetAddress mIpDst; private String mDate; private String mTime; private byte mSigPriority; private int mProtocol; private String mHostname; private String mInterfaceName; private String mPayload; private int mSport; private int mDport; private byte mType; private byte mCode; private final String LOG_TAG = "com.legind.swinedroid.AlertView"; private boolean mGotAlert; private ResolveRDNSRunnable resolveRunnable; private static final int ACTIVITY_HASH_DIALOG = 0; private static final String KEY_PROTOCOL = "protocol"; private static final String KEY_HOSTNAME = "hostname"; private static final String KEY_INTERFACE_NAME = "interface_name"; private static final String KEY_PAYLOAD = "payload"; private static final String KEY_SPORT = "sport"; private static final String KEY_DPORT = "dport"; private static final String KEY_TYPE = "type"; private static final String KEY_CODE = "code"; private static final int GENERAL_INFO_TABLE_ID = 1; private static final int IP_INFO_TABLE_ID = 2; private static final int PROTO_INFO_TABLE_ID = 3; private static final int PAYLOAD_INFO_TABLE_ID = 4; private static final int COPY_ID = 0; private static final int RDNS_ID = 1; private Menu alertViewMenu; private ImageView alertIcon; private TextView alertText; private LayoutInflater inflater; private LinearLayout layout; private RelativeLayout relativeLayout; private ClipboardManager clipboard; private String clipboardText; private TableLayout ipTableLayout; public static Activity A = null; private ErrorMessageHandler mEMH; private NetworkRunnable mNetRun = null; private class ResolveRDNSRunnable implements Runnable { private String ipSrcRDNS; private String ipDstRDNS; public void run(){ ipSrcRDNS = mIpSrc.getHostName(); ipDstRDNS = mIpDst.getHostName(); handler.sendEmptyMessage(0); } private Handler handler = new Handler(){ @Override public void handleMessage(Message msg){ String[] ipLabels = {"Src RDNS", "Dst RDNS"}; String ipSrcRDNSDisplay = ipSrcRDNS.equals(mIpSrc.getHostAddress()) ? "Could Not Resolve" : ipSrcRDNS; String ipDstRDNSDisplay = ipDstRDNS.equals(mIpDst.getHostAddress()) ? "Could Not Resolve" : ipDstRDNS; String[] ipValues = {ipSrcRDNSDisplay, ipDstRDNSDisplay}; clipboardText = clipboardText.replace("###RDNS###","\nSrc RDNS: " + ipSrcRDNSDisplay + "\nDst RDNS: " + ipDstRDNSDisplay); addRowsToTable(ipLabels, ipValues, ipTableLayout); alertViewMenu.removeItem(RDNS_ID); pdRDNS.dismiss(); CharSequence text = "RDNS info added to alert overview."; int duration = Toast.LENGTH_SHORT; Toast toast = Toast.makeText(AlertView.A, text, duration); toast.setGravity(Gravity.CENTER_VERTICAL|Gravity.CENTER_HORIZONTAL, 0, 0); toast.show(); } }; } @Override protected void onCreate(Bundle savedInstanceState) { try{ super.onCreate(savedInstanceState); A = this; mNetRun = new NetworkRunnable(this); // Open up the XML and db handlers mAlertXMLHandler = new AlertXMLHandler(); mDbHelper = new ServerDbAdapter(this); mDbHelper.open(); inflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE); layout = (LinearLayout) inflater.inflate(R.layout.alert_view, (ViewGroup) findViewById(R.id.alert_view_layout_root)); relativeLayout = (RelativeLayout) layout.findViewById(R.id.alert_view_relative_layout); mEMH = new ErrorMessageHandler(this, findViewById(R.id.server_edit_error_layout_root)); setContentView(layout); // initial value of mGotAlert is false mGotAlert = false; // create the runnable resolveRunnable = new ResolveRDNSRunnable(); alertIcon = (ImageView) layout.findViewById(R.id.alert_view_icon); alertText = (TextView) layout.findViewById(R.id.alert_view_sig_name_text); clipboard = (ClipboardManager) getSystemService(CLIPBOARD_SERVICE); if(savedInstanceState != null){ // if we have a savedInstanceState, load the strings directly mRowId = savedInstanceState.getLong(ServerDbAdapter.KEY_ROWID); mCid = savedInstanceState.getLong(AlertDbAdapter.KEY_CID); mSid = savedInstanceState.getLong(AlertDbAdapter.KEY_SID); mSigName = savedInstanceState.getString(AlertDbAdapter.KEY_SIG_NAME); mIpSrc = InetAddress.getByAddress(savedInstanceState.getByteArray(AlertDbAdapter.KEY_IP_SRC)); mIpDst = InetAddress.getByAddress(savedInstanceState.getByteArray(AlertDbAdapter.KEY_IP_DST)); mDate = savedInstanceState.getString("date"); mTime = savedInstanceState.getString("time"); mSigPriority = savedInstanceState.getByte(AlertDbAdapter.KEY_SIG_PRIORITY); mProtocol = savedInstanceState.getInt(AlertView.KEY_PROTOCOL); mHostname = savedInstanceState.getString(AlertView.KEY_HOSTNAME); mInterfaceName = savedInstanceState.getString(AlertView.KEY_INTERFACE_NAME); mPayload = savedInstanceState.getString(AlertView.KEY_PAYLOAD); mSport = savedInstanceState.getInt(AlertView.KEY_SPORT); mDport = savedInstanceState.getInt(AlertView.KEY_DPORT); mType = savedInstanceState.getByte(AlertView.KEY_TYPE); mCode = savedInstanceState.getByte(AlertView.KEY_CODE); mGotAlert = savedInstanceState.getBoolean("mGotAlert"); } else { Bundle extras = getIntent().getExtras(); if(extras != null){ // if we have an intent, construct the strings from chosen fields. add 1 to months mRowId = extras.getLong(ServerDbAdapter.KEY_ROWID); mCid = extras.getLong(AlertDbAdapter.KEY_CID); mSid = extras.getLong(AlertDbAdapter.KEY_SID); mSigName = extras.getString(AlertDbAdapter.KEY_SIG_NAME); mIpSrc = InetAddress.getByAddress(extras.getByteArray(AlertDbAdapter.KEY_IP_SRC)); mIpDst = InetAddress.getByAddress(extras.getByteArray(AlertDbAdapter.KEY_IP_DST)); mDate = extras.getString("date"); mTime = extras.getString("time"); mSigPriority = extras.getByte(AlertDbAdapter.KEY_SIG_PRIORITY); } } mNetRun.startRequestService(); } catch (UnknownHostException e) { Log.w(LOG_TAG,e.toString()); } } @Override protected void onDestroy() { mNetRun.close(); super.onDestroy(); } @Override protected void onSaveInstanceState(Bundle outState) { super.onSaveInstanceState(outState); // save not only server row, but all the search strings if(!mGotAlert) pd.dismiss(); outState.putLong(ServerDbAdapter.KEY_ROWID, mRowId); outState.putLong(AlertDbAdapter.KEY_CID, mCid); outState.putLong(AlertDbAdapter.KEY_SID, mSid); outState.putString(AlertDbAdapter.KEY_SIG_NAME, mSigName); outState.putByteArray(AlertDbAdapter.KEY_IP_SRC, mIpSrc.getAddress()); outState.putByteArray(AlertDbAdapter.KEY_IP_DST, mIpDst.getAddress()); outState.putString("date", mDate); outState.putString("time", mTime); outState.putByte(AlertDbAdapter.KEY_SIG_PRIORITY, mSigPriority); outState.putInt(AlertView.KEY_PROTOCOL, mProtocol); outState.putString(AlertView.KEY_HOSTNAME, mHostname); outState.putString(AlertView.KEY_INTERFACE_NAME, mInterfaceName); outState.putString(AlertView.KEY_PAYLOAD, mPayload); outState.putInt(AlertView.KEY_SPORT, mSport); outState.putInt(AlertView.KEY_DPORT, mDport); outState.putByte(AlertView.KEY_TYPE, mType); outState.putByte(AlertView.KEY_CODE, mCode); outState.putBoolean("mGotAlert", mGotAlert); } @Override protected void onActivityResult(int requestCode, int resultCode, Intent intent) { super.onActivityResult(requestCode, resultCode, intent); mNetRun.certificateActivityResult(requestCode, resultCode, intent, ACTIVITY_HASH_DIALOG); } @Override public boolean onCreateOptionsMenu(Menu menu) { super.onCreateOptionsMenu(menu); alertViewMenu = menu; menu.add(0, COPY_ID, 0, R.string.menu_copy_alert); menu.add(0, RDNS_ID, 0, R.string.menu_rdns_lookup); return true; } @Override public boolean onMenuItemSelected(int featureId, MenuItem item) { switch(item.getItemId()){ case COPY_ID: clipboard.setText(clipboardText.replace("###RDNS###", "")); Context context = getApplicationContext(); CharSequence text = "Alert copied to clipboard."; int duration = Toast.LENGTH_SHORT; Toast toast = Toast.makeText(context, text, duration); toast.setGravity(Gravity.CENTER_VERTICAL|Gravity.CENTER_HORIZONTAL, 0, 0); toast.show(); break; case RDNS_ID: pdRDNS = ProgressDialog.show(this, "", "Resolving RDNS...", true); Thread thread = new Thread(resolveRunnable); thread.start(); break; } return super.onMenuItemSelected(featureId, item); } protected void fillData(){ clipboardText = "Signature Name: " + mSigName + "\nSeverity: "; alertText.setText(mSigName); switch(mSigPriority){ case 1: alertIcon.setImageResource(R.drawable.low_large); clipboardText += "Low"; break; case 2: alertIcon.setImageResource(R.drawable.warn_large); clipboardText += "Medium"; break; case 3: alertIcon.setImageResource(R.drawable.high_large); clipboardText += "High"; break; } TableLayout generalTableLayout = createInfoTable("General", R.id.alert_view_sig_name_text, AlertView.GENERAL_INFO_TABLE_ID); String[] generalLabels = {"Date", "Time", "Sensor Address", "Interface"}; String[] generalValues = {mDate, mTime, mHostname, mInterfaceName}; clipboardText += "\n\nDate: " + mDate + "\nTime: " + mTime + "\nSensor Address: " + mHostname + "\nInterface: " + mInterfaceName; addRowsToTable(generalLabels, generalValues, generalTableLayout); ipTableLayout = createInfoTable("IP", AlertView.GENERAL_INFO_TABLE_ID, AlertView.IP_INFO_TABLE_ID); String[] ipLabels = {"Src Address", "Dst Address"}; String[] ipValues = {mIpSrc.getHostAddress(), mIpDst.getHostAddress()}; clipboardText += "\n\nIP Layer\nSrc Address: " + mIpSrc.getHostAddress() + "\nDst Address: " + mIpDst.getHostAddress() + "###RDNS###"; addRowsToTable(ipLabels, ipValues, ipTableLayout); String protocol = null; String[] protocolLabels = null; String[] protocolValues = null; switch(mProtocol){ case AlertXMLHandler.PROTO_ICMP: protocol = "ICMP"; String typeString = ""; String codeString = ""; switch(mType){ case 0: typeString = "Echo Reply"; break; case 3: typeString = "Destination Unreachable"; switch(mCode){ case 0: codeString = "Network Unreachable"; break; case 1: codeString = "Host Unreachable"; break; case 2: codeString = "Protocol Unreachable"; break; case 3: codeString = "Port Unreachable"; break; case 4: codeString = "Fragmentation Needed/DF set"; break; case 5: codeString = "Source Route Failed"; break; case 6: codeString = "Destination Network Unknown"; break; case 7: codeString = "Destination Host Unknown"; break; case 8: codeString = "Source Host Isolated"; break; case 9: codeString = "Communication with Destination Network is Administratively Prohibited"; break; case 10: codeString = "Communication with Destination Host is Administratively Prohibited"; break; case 11: codeString = "Destination Network Unreachable for Type of Service"; break; case 12: codeString = "Destination Host Unreachable for Type of Service"; break; case 13: codeString = "Packet filtered"; break; case 14: codeString = "Precedence violation"; break; case 15: codeString = "Precedence cut off"; break; } break; case 4: typeString = "Source Quench"; break; case 5: typeString = "Redirect"; switch(mCode){ case 0: codeString = "Redirect Datagram for the Network"; break; case 1: codeString = "Redirect Datagram for the Host"; break; case 2: codeString = "Redirect Datagram for the Type of Service and Network"; break; case 3: codeString = "Redirect Datagram for the Type of Service and Host"; break; } break; case 6: typeString = "Alternate Host Address"; switch(mCode){ case 0: codeString = "Alternate Address for Host"; break; } break; case 8: typeString = "Echo Request"; break; case 9: typeString = "Router Advertisement"; break; case 10: typeString = "Router Solicitation"; break; case 11: typeString = "Time Exceeded"; break; case 12: typeString = "Parameter Problem"; break; case 13: typeString = "Timestamp Request"; break; case 14: typeString = "Timestamp Reply"; break; case 15: typeString = "Information Request"; break; case 16: typeString = "Information Reply"; break; case 17: typeString = "Address Mask Request"; break; case 18: typeString = "Address Mask Reply"; break; case 30: typeString = "Traceroute"; break; case 31: typeString = "Datagram Conversion Error"; break; case 40: typeString = "Redirect"; switch(mCode){ case 0: codeString = "Bad SPI"; break; case 1: codeString = "Authentication Failed"; break; case 2: codeString = "Redirect Datagram for the Type of Service and Network"; break; case 3: codeString = "Decryption Failed"; break; case 4: codeString = "Need Authentication"; break; case 5: codeString = "Need Authorization"; break; } break; } protocolLabels = new String[]{"Type", "Code"}; protocolValues = new String[]{String.valueOf(mType) + (typeString.length() > 0 ? " (" + typeString + ")" : ""), String.valueOf(mCode) + (codeString.length() > 0 ? " (" + codeString + ")" : "")}; clipboardText += "\n\nICMP Layer\nType: " + String.valueOf(mType) + (typeString.length() > 0 ? " (" + typeString + ")" : "") + "\nCode: " + String.valueOf(mCode) + (codeString.length() > 0 ? " (" + codeString + ")" : ""); break; case AlertXMLHandler.PROTO_TCP: protocol = "TCP"; protocolLabels = new String[]{"Src Port", "Dst Port"}; protocolValues = new String[]{String.valueOf(mSport), String.valueOf(mDport)}; clipboardText += "\n\nTCP Layer\nSrc Port: " + String.valueOf(mSport) + "\nDst Port: " + String.valueOf(mDport); break; case AlertXMLHandler.PROTO_UDP: protocol = "UDP"; protocolLabels = new String[]{"Src Port", "Dst Port"}; protocolValues = new String[]{String.valueOf(mSport), String.valueOf(mDport)}; clipboardText += "\n\nUDP Layer\nSrc Port: " + String.valueOf(mSport) + "\nDst Port: " + String.valueOf(mDport); break; } if(protocol != null){ TableLayout protocolTableLayout = createInfoTable(protocol, AlertView.IP_INFO_TABLE_ID, AlertView.PROTO_INFO_TABLE_ID); addRowsToTable(protocolLabels, protocolValues, protocolTableLayout); } if(mPayload != null){ int parentId; if(protocol != null){ parentId = AlertView.PROTO_INFO_TABLE_ID; } else { parentId = AlertView.IP_INFO_TABLE_ID; } TableLayout payloadTableLayout = createInfoTable("Payload", parentId, AlertView.PAYLOAD_INFO_TABLE_ID); addPayloadRowsToTable(mPayload, payloadTableLayout); } } TableLayout createInfoTable(String label, int below, int id){ RelativeLayout infoTable = (RelativeLayout) inflater.inflate(R.layout.alert_view_info_table, (ViewGroup) findViewById(R.id.alert_view_info_table_layout_root)); TextView infoTableLabel = (TextView) infoTable.findViewById(R.id.alert_view_info_table_label); LayoutParams params = new RelativeLayout.LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT); params.addRule(RelativeLayout.BELOW, below); infoTableLabel.setText(label); infoTable.setLayoutParams(params); infoTable.setId(id); relativeLayout.addView(infoTable); TableLayout tableLayout = (TableLayout) infoTable.findViewById(R.id.alert_view_info_table_tablelayout); return tableLayout; } void addRowsToTable(String[] labels, String[] values, TableLayout tableLayout){ TableRow row = null; TableRow.LayoutParams paramsLeft = null; TableRow.LayoutParams paramsRight = null; TextView leftCell = null; TextView rightCell = null; for(int x = 0; x < labels.length; x++){ row = new TableRow(this); row.setWeightSum(1.0f); paramsLeft = new TableRow.LayoutParams(1); paramsLeft.weight = .4f; paramsLeft.gravity = Gravity.LEFT; paramsLeft.width = 0; paramsRight = new TableRow.LayoutParams(2); paramsRight.weight = .6f; paramsRight.gravity = Gravity.LEFT; paramsRight.width = 0; leftCell = new TextView(this); leftCell.setText(labels[x]); leftCell.setTextColor(Color.WHITE); leftCell.setLayoutParams(paramsLeft); rightCell = new TextView(this); rightCell.setText(values[x]); rightCell.setTextColor(Color.WHITE); rightCell.setLayoutParams(paramsRight); row.addView(leftCell); row.addView(rightCell); tableLayout.addView(row); } } void addPayloadRowsToTable(String hexString, TableLayout tableLayout){ try { byte[] asciiBytes = new BigInteger(hexString, 16).toByteArray(); String asciiString; asciiString = new String(asciiBytes, "US-ASCII"); clipboardText += "\n\nPayload (Hex):\n" + hexString; clipboardText += "\n\nPayload (ASCII):\n" + asciiString; int positionTracker = 0; TableRow row = null; TableRow.LayoutParams paramsCell[] = new TableRow.LayoutParams[12]; TextView cell[] = new TextView[12]; while(hexString.length() > positionTracker){ row = new TableRow(this); row.setWeightSum(1.0f); for(int i = 0; i < 12; i++){ paramsCell[i] = new TableRow.LayoutParams(); cell[i] = new TextView(this); paramsCell[i].column = i + 1; if(i < 5){ paramsCell[i].weight = .1f; } else if(i == 5){ paramsCell[i].weight = .2f; } else { paramsCell[i].weight = .05f; } paramsCell[i].gravity = Gravity.LEFT; paramsCell[i].width = 0; if(i < 6){ if(hexString.length() > positionTracker + i*2 + 1){ cell[i].setText(hexString.substring(positionTracker + i*2, positionTracker + i*2 + 2)); } } else { if(hexString.length() > positionTracker + (i - 6)*2 + 1){ if(hexString.length() > positionTracker + (i - 6)*2 + 1){ cell[i].setText(asciiString.substring(positionTracker / 2 + (i - 6), positionTracker / 2 + (i - 6) + 1).replace("\n", "")); } } } cell[i].setTextColor(Color.WHITE); cell[i].setLayoutParams(paramsCell[i]); row.addView(cell[i]); } positionTracker += 12; tableLayout.addView(row); } } catch (UnsupportedEncodingException e) { Log.w(LOG_TAG, e.toString()); } } public void callHashDialog(Intent i) { startActivityForResult(i, ACTIVITY_HASH_DIALOG); } public OnCancelListener getCancelListener() { return new OnCancelListener() { public void onCancel(DialogInterface dialog) { mDbHelper.close(); finish(); return; } }; } public Context getContext() { return this; } public ErrorMessageHandler getEMH() { return mEMH; } public Long getRowId() { return mRowId; } public void onBoundRequestSet() { if(!mGotAlert){ // Display the progress dialog first pd = ProgressDialog.show(AlertView.this, "", "Connecting. Please wait...", true); Thread thread = new Thread(mNetRun); thread.start(); } else { fillData(); } } public void onCertErrorBegin() { mGotAlert = true; } public void onCertificateInspectVerified() throws IOException, SAXException, XMLHandlerException, WebTransportException { // construct the GET arguments string, send it to the XML handler String extraArgs = "cid=" + mCid + "&sid=" + mSid; mAlertXMLHandler.createElement(mNetRun.getBoundRequest(), "alert", extraArgs); } public void onDocumentValidReturned() { mGotAlert = true; mProtocol = mAlertXMLHandler.alert.protocol; mHostname = mAlertXMLHandler.alert.hostname; mInterfaceName = mAlertXMLHandler.alert.interface_name; mPayload = mAlertXMLHandler.alert.payload; mSport = mAlertXMLHandler.alert.sport; mDport = mAlertXMLHandler.alert.dport; mType = mAlertXMLHandler.alert.type; mCode = mAlertXMLHandler.alert.code; fillData(); } public void onHandleMessageBegin() { pd.dismiss(); } }