Want to show your appreciation? Please to my charity.

Saturday, April 29, 2006

How to recover WebLogic admin password from boot.properties file

A friend came to me with a kind of locked out WebLogic 8.1 domain. He could still start the server but he didn't know the password for admin console. The fact that he could still start the server was because the username and password are stored in the boot.properties under domain directory. But they are encrypted. I told my friend that the password in the boot.properties must be a reversible as WebLogic itself needs the password to start the server. We searched string "boot.properties" in all the class files in the weblogic.jar file to find the class that does the magic. It's weblogic.security.internal.BootProperties. After 2 hours of try, we end up with code below:

import weblogic.security.internal.BootProperties;

public class RecoverPassword { 

  public static void main(String[] args) { 
    BootProperties.load(null, false);  // tested with 8.1
    // BootProperties.load("fullPathToBootPropertiesFile", false); // tested with 10.3
    BootProperties bootp = BootProperties.getBootProperties(); 

    System.out.println( 
      "#####################[" + 
       bootp.getOneClient() + "/" + bootp.getTwoClient() + 
       "]###################"); 
  }

}

Update 6/20/2009: Since many people asked me about later version of WebLogic. I took a look at the latest version 10.3 as of today. It turned out that BEA changed it a little bit. My original code, which was written for 8.1, throws the NullPointerException. But the fix is also simple, just change the call to BootProperties.load by giving the path to the boot.properties file.

We placed the above RecoverPassword.java file in c:\recover directory and compiled it. Then made a copy of startWebLogic.cmd to C:\recover\recoverPassword.cmd and added a few lines to it, nearly the end of file(first and last are existing lines).

%JAVA_HOME%\bin\java %JAVA_VM% -version
SET CLASSPATH=C:\recover;%CLASSPATH% echo %CLASSPATH%
SET SERVER_CLASS=RecoverPassword
SET doExitFlag=false
if "%WLS_REDIRECT_LOG%"=="" (

Now cd to the domain home and execute c:\recover\recoverPassword, we have the password back :-)

Friday, April 28, 2006

WebLogic 8.1.4 is leaking memory (session object).

Recently we have observed memory leakage in our production box. It turned out that it was WebLogic 8.1.4 that is leaking the session object. Some long expired sessions didn't get invalidated.

The story of how we would have suspected this in the first place would be too long to discuss it here. But here I'll present the code that we used to prove the WebLogic session leakage. The concept is simple, we used a session listener to track all the session with the help of the WeakReference. And a jsp page to display all the sessions.

The session listener first, add code below to WEB-INF/src/webpkg/SessionExplorerListener.java.

package webpkg;
import java.lang.ref.WeakReference;
import java.util.HashSet;
import java.util.Map;
import java.util.HashMap;
import java.util.Set;
import javax.servlet.http.HttpSession;
import javax.servlet.http.HttpSessionListener;
import javax.servlet.http.HttpSessionEvent;

public class SessionExplorerListener implements HttpSessionListener {
   private static final Map sessionMap = new HashMap();

  public void sessionCreated(HttpSessionEvent event) {
    HttpSession session = event.getSession();
    put(session.getId(), new WeakReference(session));
  }

  public void sessionDestroyed(HttpSessionEvent event) {
    remove(event.getSession().getId());
  }   

  public static synchronized Set getIds() {
    return new HashSet(sessionMap.keySet());
  }   

  public static synchronized HttpSession get(String id) {
    WeakReference ref = (WeakReference)sessionMap.get(id);
    return ref==null ? null : (HttpSession) ref.get();
  }

  private static synchronized void remove(String id) {
    sessionMap.remove(id);
  }   

  private static synchronized void put(String id, WeakReference ref) {
    sessionMap.put(id, ref);
  } 
}

Then let's add our listener to web.xml:

<listener>
   <listener-class>webpkg.SessionExplorerListener</listener-class>
</listener>

Finally, a jsp page that list all the active sessions, listSessions.jsp:

<%@ page language="java" contentType="text/html; charset=utf-8"
     pageEncoding="ISO-8859-1"%>
<%@ page import="java.util.*, webpkg.SessionExplorerListener" %>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
    <title>Session List</title>
  </head>
  <body>
    <% Set sessionIdSet = SessionExplorerListener.getIds(); %>
    Total Sessions: <%=sessionIdSet.size()%>
    <table border="1">
       <tr>
        <th>Session ID</th>
         <th>Create Time</th>
         <th>Last Access</th>
        <th>Timeout in (s)</th>
       </tr>
      <%
        Iterator itr = sessionIdSet.iterator();
        while(itr.hasNext()) {
          String sessionId = (String)itr.next();
          HttpSession ses = SessionExplorerListener.get(sessionId);
      %>
      <tr>
         <td>
         <% if (sessionId.equals(session.getId())) { %>
         <b><%=sessionId%></b>
         <% } else { %>
         <%=sessionId%>
         <% } %>
         </td>
         <td><%=new Date(ses.getCreationTime())%></td>
         <td><%=new Date(ses.getLastAccessedTime()) %></td>
         <td>
          <%=ses.getMaxInactiveInterval()-(System.currentTimeMillis()
             -ses.getLastAccessedTime())/1000 %>
          /
          <%=ses.getMaxInactiveInterval()%>
         </td>
      </tr>
      <%
        }
      %>
</body>
</html>

This session leaking must have been there for long, we only found this out recently because we have released a new application that puts too much in user's session. Our memory usage is kept growing with those big sessions staying there forever. The problem is rather intermittent. Most of sessions do get cleaned up. We are still unclear of what caused the WebLogic to fail.

Wednesday, April 05, 2006

A Java based TCP/IP port forwarding utility

I was looking for a port forwarding utility that I can use on a Solaris box yesterday. By searching the Internet, I found the portfwd which is a C++ utility. I downloaded to find out it didn't like my 4.x GCC. Figuring it might cost me more time and effort to rebuild an old version of GCC (without root permission), I decide to write a Java version myself so I can reuse it in other OS platforms in future.

I'm done and it is working very well. It listens on a given port and forward all connection to a destination. The port number and destination are specified in command line. I believe this utility is very useful to setup port forwarding in ad hoc basis. I have it in my USB flash drive so I can start forwarding in anywhere that Java goes.

I have file up for download at Google Code. If you do download and find it is useful, please leave a comment here so that I know somebody is using it. To start forwarding, unzip the downloaded zip file to get two jar files and do:

C:\>java -classpath commons-logging.jar;portforward.jar org.enterprisepower.net.portforward.Forwarder 8080 search.yahoo.com:80
Sep 18, 2008 1:11:14 AM org.enterprisepower.net.portforward.Listener <init>
INFO: Ready to accept client connection on 0.0.0.0:8080

Now, launch your browser and point to http://localhost:8080/ you should get the yahoo search page.

Update (9/8/2013): Source code is now at https://github.com/kennethxu/portforward, happy cloning.

Update (4/19/2009): Since I got a lot of request asking for the source code, I decided to have the source available in Google Code. Feel free to get it from the Subversion repository.