Sunday, 29 June 2014

MTPutty - Multi Tabbed Putty

If you are looking for the option where you can open Putty (free SSH and telnet client) sessions in multiple tabs, you reached to right blog. You can use MTPutty.

MTPutty is free and facilitates wrapping up multiple Putty applications in one tabbed interface. You can save user and password for remote connection to login automatically. This tool also provides facility to configure shell script that you may want to execute after remote server login. I think this is enough detail to know about MTPutty, isn’t it? If not you can refer more detail from here. Now let’s move to setting up and using MTPutty.

Installing and Setting up MTPutty

Before setting up MTPutty ensure to install Putty then only go for MTPutty installation.

Installing and setting up MTPutty in windows environment is quite simple. Download MTputty from here, execute downloaded setup file and provide the installation location. Once installation is done, you can open Mputty UI by executing ‘<mputty-installation-dir>/mtputty.exe’. When you open MTPutty first time you are prompted to provide the Putty executable file location. Once you will provide the Putty executable file location, you can see your Putty connections are imported into MPutty.


Adding New Connection in MTPutty:

To add the new connection in MTPutty, go to ‘Server > Add Server’. You will see below dialog box. Provide the required information like IP, user name, password, display name etc. and click 'OK' button.


You can see the new connection is displayed in left pane in MTputty UI. If you double click on this connection, new tab is opened in right pane and remote server is connected.

Configuring Script to Execute Automatically After Login

Right click on your added connection and click on ‘Script’ tab in opened dialog box. You need to configure two things. Wait period time and the shell script. Note that, shell script will be executed only after configured wait time. If your automatic login is done say in 3000 milliseconds, configure wait  period time around 4000 milliseconds to execute script.


I found this tool is interesting and useful. I hope this will also be useful for you. If you found this post helpful, your comments are most welcome.

Monday, 23 June 2014

Skinny War and Log4j Related Logging Issue

Recently, I packaged my web modules in EAR in skinny war fashion. With this skinny war, I managed to get the size of the EAR down to around 75 MB from 120 MB without skinny war, which is really cool. But this skinny war becomes nightmare, when I started observing log merging issue into different web application's log files at run time. I have noted down the same issue and its possible solutions in this post. If you have applied skinny war in your web modules and you are also the victim of this Log4j logging issue, I am sure you have got the right place to refer. Hope this post will help you out.

Issue: Logs are merged into single log file for different web modules which are packaged in EAR in Skinny War fashion.

I packaged all jars inside EAR/lib (including log4j.jar) so that all WAR refers to jar from this common location not from Web-INF/lib. This way there are no jars in WAR file and it refers to common location. When I deployed this EAR application, it loads the Log4j jar from EAR root (using parent first class loading policy) which is shared across all the wars. I could see application specific log files are created during server start up. But, while accessing application, logs are merged into single log file rather going to application specific log files. Below is the high level overview of EAR structure and Log4j configuration for separate web applications.

EAR Packaging Structure

 |-- META-INF
 |   `-- application.xml
 |-- lib
 |    -- jar1
 |    -- mydao.jar
 |    -- mysevice.jar
 |    -- log4j.jar
 |-- App1-1.0.0.war
 |     -- /WEB-INF/classes/App1-log4j.xml         
 `-- App2-1.0.0.war
 |     -- /WEB-INF/classes/App2-log4j.xml

Web.xml Configuration for different WARs

App1-1.0.0.war: web.xml
<context-param>
            <param-name>log4jExposeWebAppRoot</param-name>
            <param-value>false</param-value>
</context-param>
<context-param>
        <param-name>log4jConfigLocation</param-name>
        <param-value>/WEB-INF/classes/App1-log4j.xml</param-value>
</context-param>
<listener>
        <listener-class>org.springframework.web.util.Log4jConfigListener</listener-class>
</listener>

App2-1.0.0.war: web.xml:                   
<context-param>
   <param-name>log4jExposeWebAppRoot</param-name>
   <param-value>false</param-value>
</context-param>
<context-param>
    <param-name>log4jConfigLocation</param-name>
    <param-value>/WEB-INF/classes/App2-log4j.xml</param-value>
</context-param>
<listener>
      <listener-class>org.springframework.web.util.Log4jConfigListener</listener-class>
</listener>

Solution:

After digging into deep to analyze this issue, I observed Logger.getLogger() returns the logger associated to the web application which is loaded at last. That means, even though I have separate log files created specific to war, but while initializing EAR it overrides logging configuration with log4j.xml of web application which is loaded at last. That is the reason all WAR logs are written in one of the application’s log file.

To overcome this problem, I created custom Repository Selector on top of Log4j’s Repository Selector. With this custom repository selector, you can change the way how the LogManager gets a logger. You can implement this repository selector in a manner such that each context class loader has its own configuration set up with its own log4j.xml file. Using this approach, Logger.getLogger() will return a different logger based on the context class loader. You can refer these links (link1, link2) to get more detail on how you can implement your custom repository selector. With this change, I could see issue is resolved for all the classes which are packaged at web module level but not for all the classes/jars which are packaged at EAR level and shared across the web modules. So till now issue was not resolved fully. 

To resolve it fully, I started searching on net and reached to this link. Then I realized, I should check all the Logger variables in the classes which are packaged in JAR at EAR level. I found, I had below code in my service classes to get the logger instance. This static logger was also the culprit that was causing the log merging issue for the common classes which are shared across the web modules.

public class  MyServiceImpl {

      private static final Logger LOGGER = Logger.getLogger(MyServiceImpl.class);   
      private static final String CLASS_NAME = LOGGER.getName();

      // Other code here
}


I converted all static Loggers to class level instance variables. After making this change, I got log merging issue is resolved for all the classes whether those are at EAR or WAR level. 

Thanks to Repository Selector concept, that helped to solve this log merging issue across different applications. I also raised question on stack overflow for the same issue and posted my findings for other developer's references. 


Monday, 21 April 2014

Virus Scanning in Java Application using ClamAV Antivirus Engine

If you are looking for the options where you can perform virus scanning for given files and documents, this post may help you out. This post will walk you through the approach of scanning files to detect trojans, viruses, malware and other malicious threats using ClamAV. 

ClamAV is an open source antivirus engine. This engine can be used to detect Trojans, viruses, malware and other malicious threats. 

You can go through the instructions to install the ClamAV antivirus engine and integrate your JAVA application to detect virus in your files. 


Installing ClamAV on Linux Box:

Follow below instructions to install and run ClamAV services on a Linux box:

Note: C compiler must be installed on Linux box before installing ClamAV.

1.     Download ClamAV source
To: Linux box @ your desired location

2.     Extract the tar using below commands:
gzip -d clamav-0.97.tar.gz
tar –xvf clamav-0.97.tar

3.     Change command prompt to ‘clamav-0.97’ directory

4.     Run commands to define user and group
groupadd clamav

useradd -g clamav -s /bin/false -c "Clam AntiVirus" clamav


5.     Run command to configure ClamAV packages after replacing token install-root
./configure --prefix=install-root --disable-zlib-vcheck

 install-root is your own desired location to install ClamAV.


6.     Execute command to compile ClamAV source (written in c language) 

     make

7.     Execute command to install ClamAV

make install


8.     Update configuration files:

/etc/clamd.conf

·         Search ‘Example’ word and comment this line
·         Uncomment below lines:
LogTime: yes
LogSyslog yes
PidFile /var/run/clamav/clamd.pid
TemporaryDirectory /tmp
LocalSocket /var/run/clamav/clamd.socket
FixStaleSocket yes
User clamav

·         Configure and uncomment below lines. Ensure to replace token Linux_Box_IP with proper IP.

TCPAddr Linux_Box_IP
TCPSocket 3310

/etc/freshclam.conf

·         Search ‘Example’ word and comment this line
·         Uncomment below lines:
LogTime: yes

LogSyslog yes

PidFile /var/run/clamav/clamd.pid
DatabaseMirror database.clamav.net
NotifyClamd /etc/clamd.conf

9.     Start the base services to make sure they work  
  • Set command prompt to /sbin and run command
          ./configure &amp;
  •  Set command prompt to /bin and run command
          ./freshclam –d &amp;

10.  Perform manual testing to scan the file:

./clamdscan file_to_scan

Sample Output:

/home/infra/installs/clamav-0.97-installation/bin/../Party.docx: OK

----------- SCAN SUMMARY -----------
Infected files: 0
Time: 0.051 sec (0 m 0 s)


If you reached at this stage, you are done with the installation of ClamAV properly. Congratulations !!!. Now next step is to scan Virus in Java Application.

How to Scan Virus in JAVA Application

1.    Ensure to download required third party jars
2.     Use below class to plug ClamAV engine to your application. 
          
Package com.xxx.doc.utils;

import java.io.FileInputStream;
import java.io.InputStream;

import net.taldius.clamav.ClamAVScanner;
import net.taldius.clamav.ClamAVScannerFactory;

/**
 * Utility class to scan files using ClamAV antivirus APIs.
 */
public class ClamAVVirusHandler {

       // Host where 'clamd' process is running
       private String clamdHost;
      
       // Port on which 'clamd' process is listening
       private String clamdPort;
      
       // Connection time out to connect 'clamd' process
       private String connTimeOut;
      
       private ClamAVScanner scanner;
      
       public void setClamdHost(String clamdHost){
              this.clamdHost = clamdHost;
       }
      
       public String getClamdHost(){
              return this.clamdHost;
       }
      
       public void setClamdPort(String clamdPort){
              this.clamdPort = clamdPort;
       }
      
       public String getClamdPort(){
              return this.clamdPort;
       }
      
       public void setConnTimeOut(String connTimeOut){
              this.connTimeOut = connTimeOut;
       }
      
       public String getConnTimeOut(){
              return this.connTimeOut;
       }
      
       /**
        * Method to initialize clamAV scanner
        */
       public void initScanner(){
             
              ClamAVScannerFactory.setClamdHost(clamdHost);

              ClamAVScannerFactory.setClamdPort(Integer.parseInt(clamdPort));

              int connectionTimeOut = Integer.parseInt(connTimeOut);
             
              if (connectionTimeOut &gt; 0) {
                   
                 ClamAVScannerFactory.setConnectionTimeout(connectionTimeOut);
              }
              this.scanner = ClamAVScannerFactory.getScanner();
       }

       public ClamAVScanner getClamAVScanner() {
              return scanner;
       }

       /**
        * Method scans files to check whether file is virus infected
        *
        * @param destFilePath file path
        * @return
        * @throws Exception
        */
       public boolean fileScanner(String destFilePath) throws Exception  {

              return fileScanner(new FileInputStream(destFilePath));
       }

       /**
        * Method scans files to check whether file is virus infected
        *
        * @param fileInputStream
        * @return
        * @throws Exception
        */
       public boolean fileScanner(InputStream fileInputStream) throws Exception        {

              boolean resScan = false;

              if (fileInputStream != null) {

                     resScan = scanner.performScan(fileInputStream);

              } else {

                     throw new Exception();
              }
              return resScan;
       }

}

3.     Configure below in applicationContext.xml file :

        &lt;bean id="clamavutil" class="com.xxx.doc.utils.ClamAVVirusHandler" init-method="initScanner"&gt;
&lt;property name="clamdHost" value=""/&gt;
 &lt;property name="clamdPort" value=""/&gt;
 &lt;property name="connTimeOut" value="90"/&gt;  
        &lt;/bean&gt;       


Note: To configure these property values, /etc/clamd.conf file should be referred. See the below configuration       that has been made in step-8 while installing ClamAV on Linux box

TCPAddr Linux_Box_IP
TCPSocket 3310

Property Description:

clamdHost
Host where 'clamd' service is running
clamdPort
Port on which 'clamd' service is listening
connTimeOut
Connection time out while connecting 'clamd' service

4.     Use ClamAVVirusHandler to scan the file:


   // Scan file to detect virus

   boolean noVirus;

   BeanFactory beanfactory = new  ClassPathXmlApplicationContext("applicationContext.xml");
                                               
   ClamAVUtil clamAVUtil = (ClamAVUtil) beanfactory.getBean("clamavutil");
                                               
   noVirus = clamAVUtil.fileScanner(doc);
                                               
               
   if(noVirus != true){

            System.out.println("Warning !! Virus detected");
   }



N   Now try to test virus infected file using above API. If you get "Warning !! Virus detected", that means you are successfully done with integrating ClamAV in your JAVA application. Congratulations !!!.

I hope this post helped you using ClamAV antivirus engine. Looking forward for your valuable comments and feedback.