domenica 11 novembre 2012

Redeploy war in Tomcat 7 using curl and bash


 curl -T - -u user:password 'http://servername:8000/manager/text/deploy?update=true&path=/webapp' < webapp.war  

martedì 17 luglio 2012

Hardware reverse engineering - GSM Modem Da Sistemi MT0124

I bought this printed circuit board in an electronics fair. It contains a well documented GSM module by Telit and a handful of components for its powering and RS232 serial level converter (from CMOS level 2.8Volt to RS232 7.5Volt):

Even if the GSM module is well documented and even if the salesman assured me that I'd find the electric schema of circuit board on the Internet, I not found it, and I had to spend 10 hours to make the reverse engineering of pin out. 
This are the pin functions:
1. +Vcc (it works from 6 to 12 Volt)
2. bypass to RJ45 connector
3. Serial DCD (out from pcb)
4. Serial DTR (in)
5. Serial CTS (out)
6. Serial RTS (in)
7. Serial RX (out)
8. Serial TX (in)
9. Reset
10. ON/OFF (pull up, 1 sec to GND to switch on/off the GSM module)
11. bypass to RJ45 connector
12. GND



giovedì 7 giugno 2012

Get the Realm (or LoginService) instance from a ServletConxtext in Tomcat 7 and Jetty 7.5

Container-Managed Authentication is not always the best choose for implement security in web application. A typical example is when an home page have to be personalized if the current user is logged or not. With Container Managed Security, if a page isn't protected by a security-constraint, also if the current user is logged, the request.getUserPrinipal() is null.
See http://stackoverflow.com/questions/7795012/request-getuserprincipal-got-null.

A way to skip over the problem is to implement Application-Managed Authentication in web application. This means that web-app developer have to implements authentication/authorization.

But not everything is lost! We can reuse the Realm configured within application server to authenticate/authorize application's users.
There are two snippet of code that retrieve the Realm authenticator from ServletContext.

Get Tomcat 7 Realm from ServletContext:

 ApplicationContextFacade acf = (ApplicationContextFacade) servletContext;  
 Field privateField = ApplicationContextFacade.class.getDeclaredField("context");  
 privateField.setAccessible(true);  
 ApplicationContext appContext = (ApplicationContext) privateField.get(acf);  
 Field privateField2 = ApplicationContext.class.getDeclaredField("context");  
 privateField2.setAccessible(true);  
 StandardContext stdContext = (StandardContext) privateField2.get(appContext);  
 realm = stdContext.getRealm();  

The realm variable is an instance of org.apache.catalina.Realm, and you can call on this the authenticate method to authenticate and get roles of users:

 Principal principal = realm.authenticate(user, password);  
 if (principal == null)  
    return null;  
 GenericPrincipal genericPrincipal = (GenericPrincipal) principal;  
 return new DemoPrincipal(principal, genericPrincipal.getRoles());  


This is the counter part for Jetty 7.5. Be ware that normally Jetty don't allow to reach the container classes from web application class loader, we need to disable this option, see http://docs.codehaus.org/display/JETTY/Classloading.
 WebAppContext.Context context = ((org.eclipse.jetty.webapp.WebAppContext.Context) servletContext);  
 ContextHandler contextHandler = context.getContextHandler();  
 ConstraintSecurityHandler securityHandler = contextHandler  
       .getChildHandlerByClass(org.eclipse.jetty.security.ConstraintSecurityHandler.class);  
 loginService = securityHandler.getLoginService();  

 UserIdentity login = loginService.login(user, password);  
 if (login == null)  
     return null;  
 Principal principal = login.getUserPrincipal();  
 Field privateField = DefaultUserIdentity.class.getDeclaredField("_roles");  
 privateField.setAccessible(true);  
 String[] roles = (String[]) privateField.get(login);    
 return new DemoPrincipal(principal, roles);

I use Jetty with maven, this is may configuration:
 <plugin>  
      <groupId>org.mortbay.jetty</groupId>  
      <artifactId>jetty-maven-plugin</artifactId>  
      <version>${jetty.version}</version>  
      <configuration>  
           <loginServices>  
                <loginService implementation="org.eclipse.jetty.security.HashLoginService">  
                     <name>MyRealm</name>  
                     <config>${basedir}/src/main/resources/jetty-realm.properties</config>  
                </loginService>  
           </loginServices>  
           <scanIntervalSeconds>1000</scanIntervalSeconds>  
           <webAppConfig>  
                <serverClasses>  
                     <serverClass implementation="java.lang.String">  
                          -org.eclipse.jetty.  
                     </serverClass>  
                </serverClasses>  
           </webAppConfig>  
      </configuration>  
 </plugin>  

martedì 5 giugno 2012

Tell your browser to ask for save password in web AJAX login

Store password in browser is a useful functionality, the browser intercept the POST action of form and under a few condition (browser dependent) ask to store password.

Unfortunately, this mechanism don't works well when you implement a RIA (Rich Internet Application) and use AJAX call for authenticate users because your submit through XHR and not by html form submit.

I use a simple trick to show password store request from browser. After the AJAX login request complete, if the user is successful authenticate, submit the login form to a url that return a HTTP 204 status (204 NO CONTENT). The browser ask to save password but the user does not navigate anywhere else.

This is an example:

         <form method="post" action="http://demo.utilities-online.info/backend/none">  
           Username: <input id="username" type="text" name="username"><br/>  
           Password: <input id="password" type="password" name="password"><br/>  
           <input type="button" value="login" onclick="sendRequest();">  
         </form>  

try now!

Username:
Password:


Enjoy with AJAX!

giovedì 8 marzo 2012

BIRT segmentation fault on linux

I'm running BIRT in my box and experienced, several times, code dump of JVM with segmentation fault.
A problem go away when I added some options of JVM:
-Xss256k -XX:MaxPermSize=384m

Software version:
Fedora 16
JVM 1.7.0_03
Tomcat 17.0.25
BIRT 3.7.1

domenica 4 marzo 2012

Non concurrent HTTP requests on Cluster with Infinispan


On Server-Client Architecture there are two type of call, one that only retrieve information from server (Read-Only) and one that can also change server's status (R/W).
Tipically, the first one can run in concurrency, also with the same parameters, without problem (also maybe a performance increase by cache system).
The second one changes the internal server's status, create file, update database and so on. And, when several calls with same parametres reach the server simoultaneusly, problems often can occur.
When the client is a browser this problem can be mitigated with javascript, disabling button once clicked for example, but cannot be eliminated. Worse if your client isn't a browser.
There is my solution, adopted on a cluster of four machine using JBoss Infinispan.

In my webapp I use Jersey + Guice to serve request, this is a simple class that manage POST request:


      @POST  
      @Path("mpay")  
      @Produces(MEDIATYPE_WEBPAGEUTF8)  
      public Object landMPay(@QueryParam("TransactionID") String transactionId, @QueryParam("ResultCode") String resultcode) {  
           logger.debug("Get user from token, {}.", transactionId);  
           .
           .
           .


Now I want only one concurrent call with same TransactionId parameter. I created two annotation, one for Method (@UniqueCallOnCluster) and ane for Parameter (@KeyParameter).
I use first annotation as:


      @POST  
      @Path("mpay")  
      @UniqueCallOnCluster
      @Produces(MEDIATYPE_WEBPAGEUTF8)  
      public Object landMPay(@QueryParam("TransactionID") String transactionId, @QueryParam("ResultCode") String resultcode) {  
           logger.debug("Get user from token, {}.", transactionId);  
           .
           .
           .


to permit only one concurrent call with all same parameters. But I want to permit only one concurrent call with same TransactionId parameter, ignoring ResultCode values:


      @POST  
      @Path("mpay")  
      @UniqueCallOnCluster
      @Produces(MEDIATYPE_WEBPAGEUTF8)  
      public Object landMPay(@KeyParameter @QueryParam("TransactionID") String transactionId, @QueryParam("ResultCode") String resultcode) {  
           logger.debug("Get user from token, {}.", transactionId);  
           .
           .
           .


The interceptor that manage this annotations use Infinispan to tell other server that him is starting to serve this call with this parameter/s:


 
 import java.lang.annotation.Annotation;  
 import java.util.ArrayList;  
 import java.util.List;  
 import javax.transaction.TransactionManager;  
 import javax.ws.rs.core.Response;  
 import javax.ws.rs.core.Response.Status;  
 import org.aopalliance.intercept.MethodInterceptor;  
 import org.aopalliance.intercept.MethodInvocation;  
 import com.google.common.base.Joiner;  
 import com.google.inject.Inject;  


 public class UniqueCallOnClusterInterceptor implements MethodInterceptor {  


      @Inject  
      private Constants constants;  


      @Inject  
      private KeyCallOnClusterService keyCallOnClusterService;  


      public Object invoke(MethodInvocation invocation) throws Throwable {  

  
           String classname = invocation.getMethod().getDeclaringClass().getSimpleName();  
           String methodName = invocation.getMethod().getName();  
           String key = classname + "_" + methodName + "_" + extractParameterValue(invocation);  
           TransactionManager tm = keyCallOnClusterService.getTransactionManager();  

      
           try {  
                if (tm != null) {  
                     tm.begin();  
                     boolean success = keyCallOnClusterService.lock(key);  
                     if (!success) {  
                          return Response.status(Status.CONFLICT).entity("Another call with same parameter is in progress.").build();  
                     }  
                }  
                String runningServer = (String) keyCallOnClusterService.get(key);  
                if (runningServer != null) {  
                     return Response.status(Status.CONFLICT).entity("Another call with same parameter is in progress.").build();  
                }  
                keyCallOnClusterService.put(key, constants.getHostname());  
           } finally {  
                if (tm != null)  
                     tm.commit();  
           }  


           try {  
                return invocation.proceed();  
           } finally {  
                keyCallOnClusterService.remove(key);  
           }  
      }  


      public String extractParameterValue(MethodInvocation invocation) {  
           List<String> list = new ArrayList<String>();  
           Annotation[][] parameterAnnotations = invocation.getMethod().getParameterAnnotations();  
           for (int i = 0; i < parameterAnnotations.length; i++) {  
                Annotation[] annotations = parameterAnnotations[i];  
                for (int j = 0; j < annotations.length; j++) {  
                     Annotation annotation = annotations[j];  
                     if (annotation instanceof KeyParameter) {  
                          list.add(String.valueOf(invocation.getArguments()[i]));  
                          break;  
                     }  
                }  
           }  
           if (list.size() == 0)  
                return Joiner.on(", ").useForNull("null").join(invocation.getArguments());  
           return Joiner.on(", ").useForNull("null").join(list);  
      }  
 }  

The KeyCallOnClusterService class is a facility for the Infinispan's Cache Object.
Here the configuration of Infinispan:


 <?xml version="1.0" encoding="UTF-8"?>  
 <infinispan xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
      xsi:schemaLocation="urn:infinispan:config:5.1 http://www.infinispan.org/schemas/infinispan-config-5.1.xsd"  
      xmlns="urn:infinispan:config:5.1">  
      <global>  
           <globalJmxStatistics enabled="true"  
                allowDuplicateDomains="true"></globalJmxStatistics>  
           <transport clusterName="cluster"  
                distributedSyncTimeout="3000">  
                <properties>  
                     <property name="configurationFile" value="infinispan-udp.cfg.xml" />  
                </properties>  
           </transport>  
           <shutdown hookBehavior="DONT_REGISTER" />  
      </global>  
      <namedCache name="current-call-cache">  
           <jmxStatistics enabled="true" />  
           <transaction transactionMode="TRANSACTIONAL" lockingMode="PESSIMISTIC"  
                transactionManagerLookupClass="org.infinispan.transaction.lookup.GenericTransactionManagerLookup"></transaction>  
           <locking isolationLevel="REPEATABLE_READ" useLockStriping="false" />  
           <eviction strategy="LRU" maxEntries="600" />  
           <!-- Due minuti -->  
           <expiration lifespan="120000" />  
           <storeAsBinary enabled="true" />  
           <clustering mode="replication">  
                <stateTransfer timeout="5000" fetchInMemoryState="true" />  
                <sync replTimeout="5000" />  
           </clustering>  
      </namedCache>  
 </infinispan>  


The result is that when arrive concurrent request with same TransactionId, the first is served regularly, the other get a HTTP 409 Conflict.
You can use ab and wireshark to test this configuration.


Tools:
Jersey 1.6 + Guice 2.0
Google Guava 11.0.1
JBoss Infinispan 5.1.1

Good clustering at all!



lunedì 6 febbraio 2012

Port Knocking via web, Web Knocking!

Port knocking is an ingenious practice used when you want open firewall port through a predefined sequence of SYN packets to closed port. However listen to SYN packages to close port can be a weight process, specially if your system already expose a web server.

What I made is to translate the concept behind port knocking to web, instead of knocking a sequence of pre-shared port number, I send an HTTP POST with a MD5 hash of a pre-shared password plus a timestamp. A flow diagram can make my idea more clearly.




First, I have created a script to make the POST request, open-firewall.sh:

 #!/bin/sh  
 KEY=`echo SharedKey$(date +%Y%m%d%H%M) | md5sum | awk '{print $1}'`  
 wget --post-data="key=$KEY" http://SERVER/webknocking.php --delete-after  

This file contains the per-shared password (MyKey in this case) and a wget to system.

On server side, I have a file named webknocking.php that catch the key and request's source IP  and pass them to a script for verify and open firewall:

 <?php  
 $key = $_POST['key'];  
 $ip = $_SERVER['REMOTE_ADDR'];  
 $cmd = 'sudo /var/dev.zonablog.net/openfirewall-300min.sh '.$key.' '.$ip.' >> /var/log/knock.log &';  
 shell_exec($cmd);  
 ?>  
 Request forwarded.  

Notice that I call the bash script with sudo because the user that run the PHP is apache, that doesn't have rigth to change firewall configuration (iptables).
Insert into sudoers the row:

 apache     ALL=      NOPASSWD: /var/dev.zonablog.net/openfirewall-300min.sh  

to give the rigth to apache to run the script below as root. The content of openfirewall-300min.sh is:

 #!/bin/bash  
 echo " "  
 echo $(date) "Verifico Ip "$2", Key "$1  
 KEY=`echo SharedKey$(date +%Y%m%d%H%M) | md5sum | awk '{print $1}'`  
 KEY_1m=`echo SharedKey$(date --date='1 minute ago' +%Y%m%d%H%M) | md5sum | awk '{print $1}'`  
 if [ $1 != $KEY -a $1 != $KEY_1m ]  
  then  
   echo $(date) "Respingo Ip "$2", Key "$1  
   exit 1  
 fi  


 # open firewall  
 echo $(date) "Ok, apro per 5 ore"  
 /sbin/iptables -I INPUT -j ACCEPT -i eth0 -p tcp -s $2  
 sleep 180000  


 # deny incoming packets  
 echo $(date) "Chiudo a Ip "$2", Key "$1  
 /sbin/iptables -D INPUT -j ACCEPT -i eth0 -p tcp -s $2  

This file check the key of request and if it is valid, open firewall to that ip for 5 hours. The log of this operation are put in /var/log/knock.log, create this file and change the owner to apache:

 # touch /var/log/knock.log  
 # chown apache.apache /var/log/knock.log  

This is it, folks!