>From 7a577e6c3123802bbf6c9b42a57a824456fcaa33 Mon Sep 17 00:00:00 2001
From: Christina Fu <cfu@redhat.com>
Date: Thu, 31 Jul 2014 15:03:19 -0700
Subject: [PATCH] ticket#882 tokendb management, policy, and activities, 1st
 cut

---
 .../src/org/dogtagpki/tps/main/TPSBuffer.java      |  19 ++
 .../src/org/dogtagpki/server/tps/TPSServlet.java   |   4 +-
 .../src/org/dogtagpki/server/tps/TPSSession.java   |  30 ++-
 .../src/org/dogtagpki/server/tps/TPSSubsystem.java |  10 +-
 .../tps/authentication/TPSAuthenticator.java       |  10 +
 .../dogtagpki/server/tps/dbs/ActivityDatabase.java |   8 +
 .../org/dogtagpki/server/tps/dbs/TokenRecord.java  |  54 +++++
 .../org/dogtagpki/server/tps/engine/TPSEngine.java |   5 -
 .../dogtagpki/server/tps/processor/AppletInfo.java |  23 +-
 .../server/tps/processor/TPSEnrollProcessor.java   | 146 +++++++++---
 .../server/tps/processor/TPSProcessor.java         | 249 ++++++++++++++++++---
 .../dogtagpki/server/tps/rest/TokenService.java    | 114 ++++++++--
 12 files changed, 592 insertions(+), 80 deletions(-)

diff --git a/base/common/src/org/dogtagpki/tps/main/TPSBuffer.java b/base/common/src/org/dogtagpki/tps/main/TPSBuffer.java
index 43ff2ea1dae4ade8ce80cdccb4d7d5443fd17795..eea1cd8e8b6cf59970ada60ef16377cfa851b8b0 100644
--- a/base/common/src/org/dogtagpki/tps/main/TPSBuffer.java
+++ b/base/common/src/org/dogtagpki/tps/main/TPSBuffer.java
@@ -284,7 +284,26 @@ public class TPSBuffer {
             result.append(HEX_DIGITS.charAt((c & 0xF0) >> 4));
             result.append(HEX_DIGITS.charAt(c & 0x0F));
             result.append("%");
+        }
 
+        return result.toString();
+    }
+
+    /*
+     * toHexString - this version returns hex string without the'%'
+     * @return the hex representation of the buffer
+     */
+    public String toHexString2() {
+        final String HEX_DIGITS = "0123456789ABCDEF";
+
+        StringBuffer result = new StringBuffer(buf.length * 2);
+
+        for (int i = 0; i < buf.length; i++)
+        {
+            char c = (char) buf[i];
+
+            result.append(HEX_DIGITS.charAt((c & 0xF0) >> 4));
+            result.append(HEX_DIGITS.charAt(c & 0x0F));
         }
 
         return result.toString();
diff --git a/base/tps-tomcat/src/org/dogtagpki/server/tps/TPSServlet.java b/base/tps-tomcat/src/org/dogtagpki/server/tps/TPSServlet.java
index 383bd4959f4599f8e8ee670ca4c120db63e7b6cc..87c416b3ea866fa97c7e9ca276086d3a0ff2c2ff 100644
--- a/base/tps-tomcat/src/org/dogtagpki/server/tps/TPSServlet.java
+++ b/base/tps-tomcat/src/org/dogtagpki/server/tps/TPSServlet.java
@@ -51,7 +51,9 @@ public class TPSServlet extends HttpServlet {
 
         CMS.debug("TPSConnection created: " + con);
 
-        TPSSession session = new TPSSession(con);
+        String ipAddress = request.getRemoteAddr();
+
+        TPSSession session = new TPSSession(con, ipAddress);
 
         CMS.debug("TPSSession created: " + session);
 
diff --git a/base/tps-tomcat/src/org/dogtagpki/server/tps/TPSSession.java b/base/tps-tomcat/src/org/dogtagpki/server/tps/TPSSession.java
index 5584b50e87b717c3c7a040dee325ad1391e7b0b7..4a175e6980ef26416b033ad138eb53d74f61db4a 100644
--- a/base/tps-tomcat/src/org/dogtagpki/server/tps/TPSSession.java
+++ b/base/tps-tomcat/src/org/dogtagpki/server/tps/TPSSession.java
@@ -19,6 +19,7 @@ package org.dogtagpki.server.tps;
 
 import java.io.IOException;
 
+import org.dogtagpki.server.tps.dbs.TokenRecord;
 import org.dogtagpki.server.tps.processor.TPSEnrollProcessor;
 import org.dogtagpki.server.tps.processor.TPSPinResetProcessor;
 import org.dogtagpki.server.tps.processor.TPSProcessor;
@@ -33,8 +34,10 @@ import com.netscape.certsrv.apps.CMS;
 public class TPSSession {
 
     private TPSConnection connection;
+    private String ipAddress; /* remote IP */
+    private TokenRecord tokenRecord;
 
-    public TPSSession(TPSConnection conn) {
+    public TPSSession(TPSConnection conn, String ip) {
 
         if (conn == null) {
             throw new NullPointerException("TPSSession incoming connection is null!");
@@ -42,6 +45,15 @@ public class TPSSession {
 
         CMS.debug("TPSSession constructor conn: " + conn);
         connection = conn;
+
+        if (ip == null) {
+         // probably unlikely to happen; log it and continue anyway
+            CMS.debug("TPSSession constructor remote ipAddress null");
+        } else {
+            CMS.debug("TPSSession constructor remote ipAddress: " + getIpAddress());
+        }
+        setIpAddress(ip);
+
     }
 
     public TPSConnection getConnection() {
@@ -143,4 +155,20 @@ public class TPSSession {
 
     }
 
+    public TokenRecord getTokenRecord() {
+        return tokenRecord;
+    }
+
+    public void setTokenRecord(TokenRecord tokenRecord) {
+        this.tokenRecord = tokenRecord;
+    }
+
+    public String getIpAddress() {
+        return ipAddress;
+    }
+
+    private void setIpAddress(String ipAddress) {
+        this.ipAddress = ipAddress;
+    }
+
 }
diff --git a/base/tps-tomcat/src/org/dogtagpki/server/tps/TPSSubsystem.java b/base/tps-tomcat/src/org/dogtagpki/server/tps/TPSSubsystem.java
index cc67c60c964b966ba555ef2b1c33c736fdd4a6cb..0d5fe4bc4a1a61cff51d5ea3933443f3e0bf3fa1 100644
--- a/base/tps-tomcat/src/org/dogtagpki/server/tps/TPSSubsystem.java
+++ b/base/tps-tomcat/src/org/dogtagpki/server/tps/TPSSubsystem.java
@@ -19,7 +19,6 @@ package org.dogtagpki.server.tps;
 
 import org.dogtagpki.server.tps.authentication.AuthenticationManager;
 import org.dogtagpki.server.tps.cms.ConnectionManager;
-import org.dogtagpki.server.tps.profile.TokenProfileResolverManager;
 import org.dogtagpki.server.tps.config.AuthenticatorDatabase;
 import org.dogtagpki.server.tps.config.ConfigDatabase;
 import org.dogtagpki.server.tps.config.ConnectorDatabase;
@@ -29,6 +28,7 @@ import org.dogtagpki.server.tps.dbs.ActivityDatabase;
 import org.dogtagpki.server.tps.dbs.TPSCertDatabase;
 import org.dogtagpki.server.tps.dbs.TokenDatabase;
 import org.dogtagpki.server.tps.engine.TPSEngine;
+import org.dogtagpki.server.tps.profile.TokenProfileResolverManager;
 import org.mozilla.jss.CryptoManager;
 import org.mozilla.jss.CryptoManager.NotInitializedException;
 import org.mozilla.jss.crypto.ObjectNotFoundException;
@@ -71,6 +71,7 @@ public class TPSSubsystem implements IAuthority, ISubsystem {
     public AuthenticationManager authManager;
     public TokenProfileResolverManager profileResolverManager;
     public TPSEngine engine;
+    public TPSTokendb tdb;
 
     @Override
     public String getId() {
@@ -104,8 +105,11 @@ public class TPSSubsystem implements IAuthority, ISubsystem {
         connectorDatabase = new ConnectorDatabase();
         profileDatabase = new ProfileDatabase();
         profileMappingDatabase = new ProfileMappingDatabase();
+        tdb = new TPSTokendb();
+
         engine = new TPSEngine();
         engine.init();
+
     }
 
     @Override
@@ -205,6 +209,10 @@ public class TPSSubsystem implements IAuthority, ISubsystem {
         return profileResolverManager;
     }
 
+    public TPSTokendb getTokendb() {
+        return tdb;
+    }
+
     public org.mozilla.jss.crypto.X509Certificate getSubsystemCert() throws EBaseException, NotInitializedException,
             ObjectNotFoundException, TokenException {
         IConfigStore cs = CMS.getConfigStore();
diff --git a/base/tps-tomcat/src/org/dogtagpki/server/tps/authentication/TPSAuthenticator.java b/base/tps-tomcat/src/org/dogtagpki/server/tps/authentication/TPSAuthenticator.java
index 4c7bcef0fc1d44c3fdaaa145a6269b111c4d151f..8d84cf5f6afd4fbf0b6f733827a7968d56b0b00d 100644
--- a/base/tps-tomcat/src/org/dogtagpki/server/tps/authentication/TPSAuthenticator.java
+++ b/base/tps-tomcat/src/org/dogtagpki/server/tps/authentication/TPSAuthenticator.java
@@ -60,6 +60,8 @@ public class TPSAuthenticator {
     // retries if the user entered the wrong password/securid
     private int maxLoginRetries = 1;
 
+    private String authCredName;
+
     /*
      * Authentication constructor
      * @param authId authentication instance id
@@ -135,4 +137,12 @@ public class TPSAuthenticator {
     public void setNumOfRetries(int num) {
         maxLoginRetries = num;
     }
+
+    public String getAuthCredName() {
+        return authCredName;
+    }
+
+    public void setAuthCredName(String authCredName) {
+        this.authCredName = authCredName;
+    }
 }
diff --git a/base/tps-tomcat/src/org/dogtagpki/server/tps/dbs/ActivityDatabase.java b/base/tps-tomcat/src/org/dogtagpki/server/tps/dbs/ActivityDatabase.java
index 313c961ac2eae09415e56cb34df53da73a272c09..6c5211c55ca6903ba6294245760f9f0f4f7d94c7 100644
--- a/base/tps-tomcat/src/org/dogtagpki/server/tps/dbs/ActivityDatabase.java
+++ b/base/tps-tomcat/src/org/dogtagpki/server/tps/dbs/ActivityDatabase.java
@@ -35,6 +35,14 @@ import com.netscape.cmsutil.ldap.LDAPUtil;
  * @author Endi S. Dewata
  */
 public class ActivityDatabase extends LDAPDatabase<ActivityRecord> {
+    public final static String OP_DO_TOKEN = "do_token";
+    public final static String OP_ADD = "add"; // add a token
+    public final static String OP_DELETE = "delete"; // delete a token
+    //public final static String OP_MODIFY_AUDIT_SIGNING = "modify_audit_signing";
+    public final static String OP_ENROLLMENT = "enrollment";
+    public final static String OP_RENEWAL = "renewal";
+    public final static String OP_PIN_RESET = "pin_reset";
+    public final static String OP_FORMAT = "format";
 
     public ActivityDatabase(IDBSubsystem dbSubsystem, String baseDN) throws EBaseException {
         super("Activity", dbSubsystem, baseDN, ActivityRecord.class);
diff --git a/base/tps-tomcat/src/org/dogtagpki/server/tps/dbs/TokenRecord.java b/base/tps-tomcat/src/org/dogtagpki/server/tps/dbs/TokenRecord.java
index 27532bbf2154b829eae6cf68c577c875e4cd5682..b664d2a1732fa1c92692ce51f7dae58355ebe44c 100644
--- a/base/tps-tomcat/src/org/dogtagpki/server/tps/dbs/TokenRecord.java
+++ b/base/tps-tomcat/src/org/dogtagpki/server/tps/dbs/TokenRecord.java
@@ -18,8 +18,14 @@
 
 package org.dogtagpki.server.tps.dbs;
 
+import java.util.Collection;
 import java.util.Date;
+import java.util.Map;
 
+import org.dogtagpki.server.tps.TPSSubsystem;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.tps.token.TokenStatus;
 import com.netscape.cmscore.dbs.DBAttribute;
 import com.netscape.cmscore.dbs.DBObjectClasses;
 import com.netscape.cmscore.dbs.DBRecord;
@@ -195,4 +201,52 @@ public class TokenRecord extends DBRecord {
             return false;
         return true;
     }
+
+    public TokenStatus getTokenStatus() {
+        String status = getStatus();
+
+        if ("uninitialized".equals(status)) {
+            return TokenStatus.UNINITIALIZED;
+
+        } else if ("active".equals(status)) {
+            return TokenStatus.ACTIVE;
+
+        } else if ("lost".equals(status)) {
+            String reason = getReason();
+
+            if ("keyCompromise".equals(reason)) {
+                return TokenStatus.PERM_LOST;
+
+            } else if ("destroyed".equals(reason)) {
+                return TokenStatus.DAMAGED;
+
+            } else if ("onHold".equals(reason)) {
+                return TokenStatus.TEMP_LOST;
+            }
+
+        } else if ("terminated".equals(status)) {
+            return TokenStatus.TERMINATED;
+        }
+
+        return TokenStatus.PERM_LOST;
+    }
+
+    public boolean isTransitionAllowed(TokenStatus newState) {
+        boolean result = false;
+        TPSSubsystem tps = (TPSSubsystem) CMS.getSubsystem(TPSSubsystem.ID);
+        TokenStatus currentTokenStatus = getTokenStatus();
+        CMS.debug("TokenRecord.isTransitionAllowed(): current status: " + currentTokenStatus);
+        Map<TokenStatus, Collection<TokenStatus>> transitions = tps.tdb.getAllowedTransitions();
+        Collection<TokenStatus> nextStatuses = transitions.get(currentTokenStatus);
+        CMS.debug("TokenRecord.isTransitionAllowed(): allowed next statuses: " + nextStatuses);
+        if (nextStatuses == null || !nextStatuses.contains(newState)) {
+            CMS.debug("TokenRecord.isTransitionAllowed(): next status not allowed: " + newState);
+
+            result = false;
+        } else {
+            //status change allowed
+            result = true;
+        }
+        return result;
+    }
 }
diff --git a/base/tps-tomcat/src/org/dogtagpki/server/tps/engine/TPSEngine.java b/base/tps-tomcat/src/org/dogtagpki/server/tps/engine/TPSEngine.java
index dda4d3f66b39ca734130995bae8aece0bf315b34..989608d9508115ee7913e6ddc1684aeb7296ebea 100644
--- a/base/tps-tomcat/src/org/dogtagpki/server/tps/engine/TPSEngine.java
+++ b/base/tps-tomcat/src/org/dogtagpki/server/tps/engine/TPSEngine.java
@@ -234,11 +234,6 @@ public class TPSEngine {
         return keySetData;
     }
 
-    public boolean isTokenPresent(String cuid) {
-        boolean present = false;
-
-        return present;
-    }
 
     public static void main(String[] args) {
 
diff --git a/base/tps-tomcat/src/org/dogtagpki/server/tps/processor/AppletInfo.java b/base/tps-tomcat/src/org/dogtagpki/server/tps/processor/AppletInfo.java
index 88679c84a4e775afb3ca373890e3266120548ee9..4fcc7cdc77ae83eefe4d3bbdf9bbd4ad79d8cc20 100644
--- a/base/tps-tomcat/src/org/dogtagpki/server/tps/processor/AppletInfo.java
+++ b/base/tps-tomcat/src/org/dogtagpki/server/tps/processor/AppletInfo.java
@@ -10,7 +10,7 @@ public class AppletInfo {
     private byte appMajorVersion;
     private byte appMinorVersion;
 
-
+    private TPSBuffer aid;
     private TPSBuffer cuid;
     private TPSBuffer msn;
     private int totalMem;
@@ -41,7 +41,7 @@ public class AppletInfo {
         return msn;
     }
 
-    public String getCUIDString() {
+    public String getCUIDhexString(){
         if(cuid != null) {
             return cuid.toHexString();
         }
@@ -49,6 +49,17 @@ public class AppletInfo {
         return null;
     }
 
+    /*
+     * getCUIDhexString2 returns hex string without the '%'
+     */
+    public String getCUIDhexString2() {
+        if(cuid != null) {
+            return cuid.toHexString2();
+        }
+
+        return null;
+    }
+
     public String getMSNString() {
         if(msn != null) {
             return msn.toHexString();
@@ -93,4 +104,12 @@ public class AppletInfo {
         return freeMem;
     }
 
+    public TPSBuffer getAid() {
+        return aid;
+    }
+
+    public void setAid(TPSBuffer aid) {
+        this.aid = aid;
+    }
+
 }
diff --git a/base/tps-tomcat/src/org/dogtagpki/server/tps/processor/TPSEnrollProcessor.java b/base/tps-tomcat/src/org/dogtagpki/server/tps/processor/TPSEnrollProcessor.java
index 1b76c97d728ff1018b66eab998ca2c1d6ecfe9da..105452d2008285e6b190971c06a2df80954e09c2 100644
--- a/base/tps-tomcat/src/org/dogtagpki/server/tps/processor/TPSEnrollProcessor.java
+++ b/base/tps-tomcat/src/org/dogtagpki/server/tps/processor/TPSEnrollProcessor.java
@@ -15,11 +15,14 @@ import netscape.security.util.BigInt;
 import netscape.security.x509.X509CertImpl;
 
 import org.dogtagpki.server.tps.TPSSession;
+import org.dogtagpki.server.tps.TPSSubsystem;
 import org.dogtagpki.server.tps.authentication.TPSAuthenticator;
 import org.dogtagpki.server.tps.channel.SecureChannel;
 import org.dogtagpki.server.tps.channel.SecureChannel.TokenKeyType;
 import org.dogtagpki.server.tps.cms.CAEnrollCertResponse;
 import org.dogtagpki.server.tps.cms.CARemoteRequestHandler;
+import org.dogtagpki.server.tps.dbs.ActivityDatabase;
+import org.dogtagpki.server.tps.dbs.TokenRecord;
 import org.dogtagpki.server.tps.engine.TPSEngine;
 import org.dogtagpki.server.tps.main.ObjectSpec;
 import org.dogtagpki.server.tps.main.PKCS11Obj;
@@ -36,13 +39,13 @@ import com.netscape.certsrv.authentication.IAuthCredentials;
 import com.netscape.certsrv.authentication.IAuthToken;
 import com.netscape.certsrv.base.EBaseException;
 import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.tps.token.TokenStatus;
 import com.netscape.cmsutil.util.Utils;
 
 public class TPSEnrollProcessor extends TPSProcessor {
 
     public TPSEnrollProcessor(TPSSession session) {
         super(session);
-
     }
 
     @Override
@@ -61,30 +64,74 @@ public class TPSEnrollProcessor extends TPSProcessor {
 
     private void enroll() throws TPSException, IOException {
         CMS.debug("TPSEnrollProcessor enroll: entering...");
+        String auditMsg = null;
         TPSEngine engine = getTPSEngine();
-        AppletInfo appletInfo = getAppletInfo();
+        TPSSubsystem tps = (TPSSubsystem) CMS.getSubsystem(TPSSubsystem.ID);
+
+        AppletInfo appletInfo = null;
+        TokenRecord tokenRecord = null;
+        try {
+            appletInfo = getAppletInfo();
+        } catch (TPSException e) {
+            auditMsg = e.toString();
+            try {
+                tps.tdb.tdbActivity(tps, ActivityDatabase.OP_ENROLLMENT, tokenRecord, session.getIpAddress(),
+                    auditMsg, "failure");
+            } catch (Exception ea) {
+                auditMsg = auditMsg + ";" +" tokendb activity logging failure: "+ ea;
+            }
+            throw e;
+        }
+        appletInfo.setAid(getCardManagerAID());
+        boolean isTokenPresent = false;
+        tokenRecord = createTokenRecord(isTokenPresent, appletInfo);
+        session.setTokenRecord(tokenRecord);
+
         String resolverInstName = getResolverInstanceName();
 
         String tokenType = null;
 
-        tokenType = resolveTokenProfile(resolverInstName, appletInfo.getCUIDString(), appletInfo.getMSNString(),
+        tokenType = resolveTokenProfile(resolverInstName, appletInfo.getCUIDhexString(), appletInfo.getMSNString(),
                 appletInfo.getMajorVersion(), appletInfo.getMinorVersion());
-        CMS.debug("TPSProcessor.enroll: calculated tokenType: " + tokenType);
-        CMS.debug("TPSEnrollProcessor.enroll: tokenType: " + tokenType);
+        CMS.debug("TPSEnrollProcessor.enroll: resolved tokenType: " + tokenType);
 
         checkProfileStateOK();
 
-        if (engine.isTokenPresent(appletInfo.getCUIDString())) {
-            //ToDo
+        boolean do_force_format = false;
+        if (isTokenPresent) {
+            CMS.debug("TPSEnrollProcessor.enroll: token exists");
 
+            TokenStatus newState = TokenStatus.ACTIVE;
+            // Check for transition to ATIVE status.
+            if(!tokenRecord.isTransitionAllowed(newState )) {
+                CMS.debug("TPSEnrollProcessor.enroll: token transition disallowed " +
+                        tokenRecord.getTokenStatus() +
+                        " to " + newState);
+                auditMsg = "Operation for CUID "+appletInfo.getCUIDhexString2()+
+                        " Disabled, illegal transition attempted " + tokenRecord.getTokenStatus() +
+                        " to " + newState;
+                try {
+                    tps.tdb.tdbActivity(tps, ActivityDatabase.OP_ENROLLMENT, tokenRecord, session.getIpAddress(),
+                            auditMsg, "failure");
+                } catch (Exception ea) {
+                    auditMsg = auditMsg + ";" + " tokendb activity logging failure: " + ea;
+                }
+                throw new TPSException(auditMsg,
+                        TPSStatus.STATUS_ERROR_DISABLED_TOKEN);
+            } else {
+                CMS.debug("TPSPEnrollrocessor.enroll: token transition allowed "+
+                        tokenRecord.getTokenStatus() +
+                        " to " + newState);
+            }
+            do_force_format = engine.raForceTokenFormat(appletInfo.getCUIDhexString());
         } else {
+            CMS.debug("TPSEnrollProcessor.enroll: token does not exist");
+            tokenRecord.setStatus("uninitialized");
+
             checkAllowUnknownToken(TPSEngine.OP_FORMAT_PREFIX);
-            checkAndAuthenticateUser(appletInfo, tokenType);
         }
+        checkAndAuthenticateUser(appletInfo, tokenType);
 
-        //ToDo: check transition state here
-
-        boolean do_force_format = engine.raForceTokenFormat(appletInfo.getCUIDString());
 
         if (do_force_format) {
             CMS.debug("TPSEnrollProcessor.enroll: About to force format first due to policy.");
@@ -106,7 +153,7 @@ public class TPSEnrollProcessor extends TPSProcessor {
         //Reset the token's pin, create one if we don't have one already
 
         checkAndHandlePinReset(channel);
-
+        tokenRecord.setKeyInfo(channel.getKeyInfoData().toHexString2());
         String tksConnId = getTKSConnectorID();
         TPSBuffer plaintextChallenge = computeRandomData(16, tksConnId);
 
@@ -117,12 +164,31 @@ public class TPSEnrollProcessor extends TPSProcessor {
         try {
             pkcs11objx = getCurrentObjectsOnToken(channel);
         } catch (DataFormatException e) {
-            throw new TPSException("TPSEnrollProcessor.enroll: Failed to parse original token data: " + e.toString());
+            auditMsg = "TPSEnrollProcessor.enroll: Failed to parse original token data: " + e.toString();
+            try {
+                tps.tdb.tdbActivity(tps, ActivityDatabase.OP_ENROLLMENT, tokenRecord, session.getIpAddress(),
+                    auditMsg, "failure");
+            } catch (Exception ea) {
+                auditMsg = auditMsg + ";" +" tokendb activity logging failure: "+ ea;
+            }
+            throw new TPSException(auditMsg);
         }
 
         pkcs11objx.setCUID(appletInfo.getCUID());
-        //ToDo: Add token to token db
 
+        try {
+            tokenRecord.setStatus("active");
+            tps.tdb.tdbUpdateTokenEntry(tps, tokenRecord);
+        } catch (Exception e){
+            auditMsg = "TPSEnrollProcessor.enroll: Failed to add token: " + e.toString();
+            try {
+                tps.tdb.tdbActivity(tps, ActivityDatabase.OP_ENROLLMENT, tokenRecord, session.getIpAddress(),
+                    auditMsg, "failure");
+            } catch (Exception ea) {
+                auditMsg = auditMsg + ";" +" tokendb activity logging failure: "+ ea;
+            }
+            throw new TPSException(auditMsg);
+        }
         statusUpdate(10, "PROGRESS_PROCESS_PROFILE");
 
         EnrolledCertsInfo certsInfo = new EnrolledCertsInfo();
@@ -168,6 +234,15 @@ public class TPSEnrollProcessor extends TPSProcessor {
         statusUpdate(99, "PROGRESS_SET_LIFECYCLE");
         channel.setLifeycleState((byte) 0x0f);
 
+        auditMsg = "enroll operation succeeded";
+        try {
+            tps.tdb.tdbActivity(tps, ActivityDatabase.OP_ENROLLMENT, tokenRecord, session.getIpAddress(), auditMsg, "success");
+
+        } catch (Exception ea) {
+            auditMsg = auditMsg + ";" + " tokendb activity logging failure: " + ea;
+            //nothing to do here; log it and continue
+            CMS.debug(auditMsg);
+        }
         CMS.debug("TPSEnrollProcessor.enroll: leaving ...");
 
         statusUpdate(100, "PROGRESS_DONE_ENROLLMENT");
@@ -232,10 +307,15 @@ public class TPSEnrollProcessor extends TPSProcessor {
     private void checkAndAuthenticateUser(AppletInfo appletInfo, String tokenType) throws TPSException {
         IAuthCredentials userCred;
         IAuthToken authToken;
+        TokenRecord tokenRecord = getTokenRecord();
         if (!isExternalReg) {
             // authenticate per profile/tokenType configuration
             String configName = TPSEngine.OP_ENROLL_PREFIX + "." + tokenType + ".auth.enable";
             IConfigStore configStore = CMS.getConfigStore();
+
+            TPSSubsystem tps =
+                (TPSSubsystem) CMS.getSubsystem(TPSSubsystem.ID);
+            //TPSSession session = getSession();
             boolean isAuthRequired;
             try {
                 CMS.debug("TPSEnrollProcessor.checkAndAuthenticateUser: getting config: " + configName);
@@ -250,17 +330,31 @@ public class TPSEnrollProcessor extends TPSProcessor {
                 try {
                     TPSAuthenticator userAuth =
                             getAuthentication(TPSEngine.OP_ENROLL_PREFIX, tokenType);
-                    userCred = requestUserId(TPSEngine.ENROLL_OP, appletInfo.getCUIDString(), userAuth,
+                    userCred = requestUserId(TPSEngine.ENROLL_OP, appletInfo.getCUIDhexString(), userAuth,
                             beginMsg.getExtensions());
+                    userid = (String)userCred.get(userAuth.getAuthCredName());
+                    CMS.debug("TPSEnrollProcessor.checkAndAuthenticateUser: userCred (attempted) userid=" + userid);
+                    // initialize userid first for logging purposes in case authentication fails
+                    tokenRecord.setUserID(userid);
                     authToken = authenticateUser(TPSEngine.ENROLL_OP, userAuth, userCred);
+                    userid = authToken.getInString("userid");
+                    tokenRecord.setUserID(userid);
                     CMS.debug("TPSEnrollProcessor.checkAndAuthenticateUser: auth passed: userid: "
                             + authToken.get("userid"));
-                    userid = authToken.getInString("userid");
+
                 } catch (Exception e) {
                     // all exceptions are considered login failure
                     CMS.debug("TPSEnrollProcessor.checkAndAuthenticateUser:: authentication exception thrown: " + e);
-                    throw new TPSException("TPS error user authentication failed.",
-                            TPSStatus.STATUS_ERROR_LOGIN);
+                    String msg = "TPS error user authentication failed:" + e;
+                    try {
+                        tps.tdb.tdbActivity(tps, ActivityDatabase.OP_ENROLLMENT, tokenRecord, session.getIpAddress(),
+                            "authentication error", "failure");
+                    } catch (Exception ea) {
+                        msg = msg + ";" +" tokendb activity logging failure: "+ ea;
+                    }
+
+                    throw new TPSException(msg,
+                             TPSStatus.STATUS_ERROR_LOGIN);
                 }
             } else {
                 throw new TPSException(
@@ -277,7 +371,7 @@ public class TPSEnrollProcessor extends TPSProcessor {
         CMS.debug("TPSEnrollProcessor.checkAndHandlePinReset entering...");
 
         if (channel == null) {
-            throw new TPSException("TPSProcessor.checkAndHandlePinReset: invalid input data!",
+            throw new TPSException("TPSEnrollProcessor.checkAndHandlePinReset: invalid input data!",
                     TPSStatus.STATUS_ERROR_TOKEN_RESET_PIN_FAILED);
         }
 
@@ -358,8 +452,8 @@ public class TPSEnrollProcessor extends TPSProcessor {
             securityLevel = SecurityLevel.SECURE_MSG_MAC_ENC;
 
         if (checkForAppletUpdateEnabled()) {
-            String targetAppletVersion = checkForAppletUpgrade(currentTokenOperation);
-            upgradeApplet(currentTokenOperation, targetAppletVersion, securityLevel, getBeginMessage().getExtensions(),
+            String targetAppletVersion = checkForAppletUpgrade("op."+currentTokenOperation);
+            upgradeApplet("op."+currentTokenOperation, targetAppletVersion, securityLevel, getBeginMessage().getExtensions(),
                     tksConnId, 5, 12);
         }
 
@@ -519,7 +613,7 @@ public class TPSEnrollProcessor extends TPSProcessor {
 
         Map<String, String> nv = new LinkedHashMap<String, String>();
 
-        nv.put("cuid", ainfo.getCUIDString());
+        nv.put("cuid", ainfo.getCUIDhexString());
         nv.put("msn", ainfo.getMSNString());
         nv.put("userid", userid);
         nv.put("auth.cn", userid);
@@ -748,9 +842,9 @@ public class TPSEnrollProcessor extends TPSProcessor {
                 AppletInfo appletInfo = getAppletInfo();
                 selectCoolKeyApplet();
                 CMS.debug("TPSEnrollProcessor.enrollOneCertificate:: userid =" + userid + ", cuid="
-                        + appletInfo.getCUIDString());
+                        + appletInfo.getCUIDhexString());
                 CAEnrollCertResponse caEnrollResp = caRH.enrollCertificate(encodedParsedPubKey, userid,
-                        appletInfo.getCUIDString(), getSelectedTokenType(),
+                        appletInfo.getCUIDhexString(), getSelectedTokenType(),
                         cEnrollInfo.getKeyType());
                 String retCertB64 = caEnrollResp.getCertB64();
 
@@ -779,7 +873,7 @@ public class TPSEnrollProcessor extends TPSProcessor {
 
                 certsInfo.addCertificate(x509Cert);
                 certsInfo.addKType(cEnrollInfo.getKeyType());
-                certsInfo.addOrigin(aInfo.getCUIDString());
+                certsInfo.addOrigin(aInfo.getCUIDhexString());
 
                 SubjectPublicKeyInfo publicKeyInfo = null;
                 try {
@@ -910,7 +1004,7 @@ public class TPSEnrollProcessor extends TPSProcessor {
 
         Map<String, String> nv = new LinkedHashMap<String, String>();
 
-        nv.put("cuid", ainfo.getCUIDString());
+        nv.put("cuid", ainfo.getCUIDhexString());
         nv.put("msn", ainfo.getMSNString());
         nv.put("userid", userid);
         nv.put("auth.cn", userid);
diff --git a/base/tps-tomcat/src/org/dogtagpki/server/tps/processor/TPSProcessor.java b/base/tps-tomcat/src/org/dogtagpki/server/tps/processor/TPSProcessor.java
index bb2d1a9f51f37a8eca73277687975c663dd01464..dce26fcb4deed90f9205048ea2f1d9fcca6ee5e1 100644
--- a/base/tps-tomcat/src/org/dogtagpki/server/tps/processor/TPSProcessor.java
+++ b/base/tps-tomcat/src/org/dogtagpki/server/tps/processor/TPSProcessor.java
@@ -37,6 +37,8 @@ import org.dogtagpki.server.tps.cms.TKSComputeRandomDataResponse;
 import org.dogtagpki.server.tps.cms.TKSComputeSessionKeyResponse;
 import org.dogtagpki.server.tps.cms.TKSEncryptDataResponse;
 import org.dogtagpki.server.tps.cms.TKSRemoteRequestHandler;
+import org.dogtagpki.server.tps.dbs.ActivityDatabase;
+import org.dogtagpki.server.tps.dbs.TokenRecord;
 import org.dogtagpki.server.tps.engine.TPSEngine;
 import org.dogtagpki.server.tps.profile.BaseTokenProfileResolver;
 import org.dogtagpki.server.tps.profile.TokenProfileParams;
@@ -73,6 +75,7 @@ import com.netscape.certsrv.authentication.IAuthToken;
 import com.netscape.certsrv.base.EBaseException;
 import com.netscape.certsrv.base.EPropertyNotFound;
 import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.tps.token.TokenStatus;
 import com.netscape.symkey.SessionKey;
 
 public class TPSProcessor {
@@ -94,9 +97,10 @@ public class TPSProcessor {
     protected boolean isExternalReg;
 
     protected TPSSession session;
+    //protected TokenRecord tokenRecord;
     protected String selectedTokenType;
 
-    protected String userid;
+    protected String userid = null;
     protected String currentTokenOperation;
 
     protected BeginOpMsg beginMsg;
@@ -120,6 +124,11 @@ public class TPSProcessor {
         return session;
     }
 
+    protected TokenRecord getTokenRecord() {
+        TPSSession session = getSession();
+        return session.getTokenRecord();
+    }
+
     protected void setBeginMessage(BeginOpMsg msg) {
         beginMsg = msg;
     }
@@ -133,7 +142,12 @@ public class TPSProcessor {
         if (theTokenType == null) {
             throw new NullPointerException("TPSProcessor.setSelectedTokenType: Attempt to set invalid null token type!");
         }
+        CMS.debug("TPS_Processor.setSelectedTokenType: tokenType="+
+                theTokenType);
         selectedTokenType = theTokenType;
+
+        TokenRecord tokenRecord = getTokenRecord();
+        tokenRecord.setType(selectedTokenType);
     }
 
     public String getSelectedTokenType() {
@@ -410,6 +424,9 @@ public class TPSProcessor {
         TPSBuffer key_info_data = initUpdateResp.substr(DIVERSIFICATION_DATA_SIZE, 2);
         CMS.debug("TPSProcessor.setupSecureChannel: key info data: " + key_info_data.toHexString());
 
+        TokenRecord tokenRecord = getTokenRecord();
+        tokenRecord.setKeyInfo(key_info_data.toHexString2());
+
         TPSBuffer card_cryptogram = initUpdateResp.substr(CARD_CRYPTOGRAM_OFFSET, CARD_CRYPTOGRAM_SIZE);
         CMS.debug("TPSProcessor.setupSecureChannel: card cryptogram: " + card_cryptogram.toHexString());
 
@@ -534,6 +551,8 @@ public class TPSProcessor {
 
         byte[] appletData = null;
 
+        TokenRecord tokenRecord = getTokenRecord();
+
         String directory = getAppletDirectory(operation);
 
         CMS.debug("TPSProcessor.upgradeApplet: applet target directory: " + directory);
@@ -549,7 +568,7 @@ public class TPSProcessor {
         APDUResponse select = selectApplet((byte) 0x04, (byte) 0x00, cardMgrAIDBuff);
 
         if (!select.checkResult()) {
-            throw new TPSException("TPSProcessor.format: Can't selelect the card manager!");
+            throw new TPSException("TPSProcessor.upgradeApplet: Can't selelect the card manager!");
         }
 
         SecureChannel channel = setupSecureChannel((byte) defKeyVersion, (byte) defKeyIndex, securityLevel, connId);
@@ -578,6 +597,7 @@ public class TPSProcessor {
             throw new TPSException("TPSProcessor.upgradeApplet: Cannot select newly created applet!",
                     TPSStatus.STATUS_ERROR_UPGRADE_APPLET);
         }
+        tokenRecord.setAppletID(new_version);
 
     }
 
@@ -629,9 +649,12 @@ public class TPSProcessor {
     public TPSAuthenticator getAuthentication(String prefix, String tokenType)
             throws EBaseException {
         CMS.debug("TPSProcessor.getAuthentication");
+        String auditMsg = null;
+
         if (prefix.isEmpty() || tokenType.isEmpty()) {
-            CMS.debug("TPSProcessor.getAuthentication: missing parameters: prefix or tokenType");
-            throw new EBaseException("TPSProcessor.getAuthentication: missing parameters: prefix or tokenType");
+            auditMsg = "TPSProcessor.getAuthentication: missing parameters: prefix or tokenType";
+            CMS.debug(auditMsg);
+            throw new EBaseException(auditMsg);
         }
         IConfigStore configStore = CMS.getConfigStore();
         String configName = prefix + "." + tokenType + ".auth.id";
@@ -640,11 +663,26 @@ public class TPSProcessor {
         CMS.debug("TPSProcessor.getAuthentication: getting config: " +
                 configName);
         authId = configStore.getString(configName);
+        if (authId == null) {
+            auditMsg = "TPSProcessor.getAuthentication: config param not found:" + configName;
+            CMS.debug(auditMsg);
+            throw new EBaseException(auditMsg);
+        }
 
         TPSSubsystem subsystem =
                 (TPSSubsystem) CMS.getSubsystem(TPSSubsystem.ID);
         TPSAuthenticator authInst =
                 subsystem.getAuthenticationManager().getAuthInstance(authId);
+        String authCredNameConf = "auths.instance."+ authId + ".authCredName";
+        CMS.debug("TPSProcessor.getAuthentication: getting config: " +
+                authCredNameConf);
+        String authCredName = configStore.getString(authCredNameConf);
+        if (authCredName == null) {
+            auditMsg = "TPSProcessor.getAuthentication: config param not found:"+ authCredNameConf;
+           CMS.debug(auditMsg);
+            throw new EBaseException(auditMsg);
+        }
+        authInst.setAuthCredName(authCredName);
         return authInst;
     }
 
@@ -652,8 +690,7 @@ public class TPSProcessor {
      * authenticateUser authenticates a user using specified authentication
      *
      * @param op "enrollment", "format", or "pinReset" //TODO: for tokendb activity log
-     * @param prefix "op.enroll", "op.format", or "op.pinReset"
-     * @param tokenType the profile name
+     * @param userAuth the authenticator
      * @param userCred IAuthCredentials obtained from a successful requestUserId call
      * @return IAuthToken information relating to the performed authentication
      *         -- plugin-specific
@@ -666,10 +703,12 @@ public class TPSProcessor {
         /**
          * TODO: isExternalReg is not handled until decision made
          */
+        String auditMsg = null;
         CMS.debug("TPSProcessor.authenticateUser");
         if (op.isEmpty() || userAuth == null || userCred == null) {
-            CMS.debug("TPSProcessor.authenticateUser: missing parameter(s): op, userAuth, or userCred");
-            throw new EBaseException("TPSProcessor.getAuthentication: missing parameter(s): op, userAuth, or userCred");
+            auditMsg = "TPSProcessor.authenticateUser: missing parameter(s): op, userAuth, or userCred";
+            CMS.debug(auditMsg);
+            throw new EBaseException(auditMsg);
         }
         IAuthManager auth = userAuth.getAuthManager();
 
@@ -773,6 +812,8 @@ public class TPSProcessor {
         String[] requiredCreds = auth.getAuthManager().getRequiredCreds();
         for (String cred : requiredCreds) {
             String name = auth.getCredMap(cred, extendedLogin);
+            CMS.debug("TPSProcessor.mapCredFromMsgResponse: cred="+cred+ " &name="+
+                    name);
             login.set(cred, response.get(name));
         }
 
@@ -855,21 +896,88 @@ public class TPSProcessor {
         return login;
     }
 
+    /*
+     * createTokenRecord -
+     *     - retrieves token record from tokendb if it exists, or
+     *     - creates a new token record
+     *     - sets the isTokenPresent to true if token found in tokendb
+     *     this in-memory copy of tokenRecord is to be set in the TPSSession
+     */
+    protected TokenRecord createTokenRecord(boolean isTokenPresent, AppletInfo appletInfo)
+            throws TPSException {
+        CMS.debug("TPSProcessor.createTokenRecord: begins");
+        if (appletInfo == null) {
+            CMS.debug("TPSProcessor.createTokenRecord: param appletInfo cannot be null");
+            throw new TPSException(
+                    "TPSProcessor.requestExtendedLogin: missing parameter(s): parameter appletInfo");
+        }
+        TPSSubsystem tps = (TPSSubsystem) CMS.getSubsystem(TPSSubsystem.ID);
+        TokenRecord tokenRecord = null;
+
+        try {
+            TokenRecord gotToken = tps.tdb.tdbGetTokenEntry(tps, appletInfo.getCUIDhexString2());
+            // now the in memory tokenRecord is replaced by the actual token data
+            tokenRecord = gotToken;
+            CMS.debug("TPSProcessor.createTokenRecord: found token...");
+            isTokenPresent = true;
+        } catch (Exception e) {
+            CMS.debug("TPSProcessor.createTokenRecord: token does not exist...");
+            tokenRecord = new TokenRecord();
+            tokenRecord.setId(appletInfo.getCUIDhexString2());
+        }
+
+        byte app_major_version = appletInfo.getAppMajorVersion();
+        byte app_minor_version = appletInfo.getAppMinorVersion();
+        TPSBuffer build_id = null;
+        try {
+            build_id = getAppletVersion();
+        } catch (IOException e) {
+            CMS.debug("TPSProcessor.createTokenRecord: failed getting applet version:" + e + " ... continue");
+        }
+        if (build_id != null) {
+            tokenRecord.setAppletID(Integer.toHexString(app_major_version) + "." + Integer.toHexString(app_minor_version) + "."+
+                    build_id.toHexString2());
+        }
+
+        CMS.debug("TPSProcessor.createTokenRecord: ends");
+
+        return tokenRecord;
+    }
+
     protected void format(boolean skipAuth) throws TPSException, IOException {
 
+        String auditMsg = null;
         String appletVersion = null;
 
         TPSSubsystem tps = (TPSSubsystem) CMS.getSubsystem(TPSSubsystem.ID);
-        TPSEngine engine = tps.getEngine();
 
         boolean isExternalReg = false;
-        AppletInfo appletInfo = getAppletInfo();
+        AppletInfo appletInfo = null;
+        TokenRecord tokenRecord = null;
+        try {
+            appletInfo = getAppletInfo();
+        } catch (TPSException e) {
+            auditMsg = e.toString();
+            try {
+                tps.tdb.tdbActivity(tps, ActivityDatabase.OP_FORMAT, tokenRecord, session.getIpAddress(),
+                    auditMsg, "failure");
+            } catch (Exception ea) {
+                auditMsg = auditMsg + ";" +" tokendb activity logging failure: "+ ea;
+            }
+            throw e;
+        }
+        appletInfo.setAid(getCardManagerAID());
+        boolean isTokenPresent = false;
+        tokenRecord = createTokenRecord(isTokenPresent, appletInfo);
+        session.setTokenRecord(tokenRecord);
 
-        String cuid = appletInfo.getCUIDString();
+        String cuid = appletInfo.getCUIDhexString();
+        CMS.debug("TPSProcessor.format: CUID hex string=" + appletInfo.getCUIDhexString2());
+        //tokenRecord.setId(appletInfo.getCUIDhexString(true));
         String msn = appletInfo.getMSNString();
 
         byte major_version = appletInfo.getMajorVersion();
-        byte minor_version = appletInfo.getAppMinorVersion();
+        byte minor_version = appletInfo.getMinorVersion();
         byte app_major_version = appletInfo.getAppMajorVersion();
         byte app_minor_version = appletInfo.getAppMinorVersion();
 
@@ -891,7 +999,18 @@ public class TPSProcessor {
              *    plugin used (tokenType resolved perhaps via authentication)
              */
 
-            tokenType = resolveTokenProfile(resolverInstName, cuid, msn, major_version, minor_version);
+            try {
+                tokenType = resolveTokenProfile(resolverInstName, cuid, msn, major_version, minor_version);
+            } catch (TPSException e) {
+                auditMsg = e.toString();
+                try {
+                    tps.tdb.tdbActivity(tps, ActivityDatabase.OP_FORMAT, tokenRecord, session.getIpAddress(),
+                        auditMsg, "failure");
+                } catch (Exception ea) {
+                    auditMsg = auditMsg + ";" +" tokendb activity logging failure: "+ ea;
+                }
+                throw new TPSException(auditMsg,TPSStatus.STATUS_ERROR_MISCONFIGURATION);
+            }
             CMS.debug("TPSProcessor.format: calculated tokenType: " + tokenType);
         }
 
@@ -906,24 +1025,45 @@ public class TPSProcessor {
                 isAuthRequired = configStore.getBoolean(configName, true);
             } catch (EBaseException e) {
                 CMS.debug("TPSProcessor.format: Internal Error obtaining mandatory config values. Error: " + e);
-                throw new TPSException("TPS error getting config values from config store.",
-                        TPSStatus.STATUS_ERROR_MISCONFIGURATION);
+                auditMsg = "TPS error getting config values from config store." + e.toString();
+                try {
+                    tps.tdb.tdbActivity(tps, ActivityDatabase.OP_FORMAT, tokenRecord, session.getIpAddress(),
+                        auditMsg, "failure");
+                } catch (Exception ea) {
+                    auditMsg = auditMsg + ";" +" tokendb activity logging failure: "+ ea;
+                }
+                throw new TPSException(auditMsg, TPSStatus.STATUS_ERROR_MISCONFIGURATION);
             }
+
             if (isAuthRequired && !skipAuth) {
                 try {
                     TPSAuthenticator userAuth =
                             getAuthentication(TPSEngine.OP_FORMAT_PREFIX, tokenType);
                     userCred = requestUserId("format", cuid, userAuth, beginMsg.getExtensions());
+                    userid = (String) userCred.get(userAuth.getAuthCredName());
+                    CMS.debug("TPSProcessor.format: userCred (attempted) userid=" + userid);
+                    // initialize userid first for logging purposes in case authentication fails
+                    tokenRecord.setUserID(userid);
                     IAuthToken authToken = authenticateUser("format", userAuth, userCred);
                     userid = authToken.getInString("userid");
+                    tokenRecord.setUserID(userid);
                     CMS.debug("TPSProcessor.format:: auth token userid=" + userid);
+                    // TODO: should check if userid match?
                 } catch (Exception e) {
                     // all exceptions are considered login failure
                     CMS.debug("TPSProcessor.format:: authentication exception thrown: " + e);
-                    throw new TPSException("TPS error user authentication failed.",
+                    auditMsg = "authentication failed, status = STATUS_ERROR_LOGIN";
+
+                    try {
+                        tps.tdb.tdbActivity(tps, ActivityDatabase.OP_FORMAT, tokenRecord, session.getIpAddress(),
+                                auditMsg, "failure");
+                    } catch (Exception ea) {
+                        auditMsg = auditMsg + ";" + " tokendb activity logging failure: " + ea;
+                    }
+                    throw new TPSException(auditMsg,
                             TPSStatus.STATUS_ERROR_LOGIN);
                 }
-            }
+            } // TODO: if no auth required, should wipe out existing tokenRecord entry data later?
         }
 
         /**
@@ -935,10 +1075,34 @@ public class TPSProcessor {
 
         checkProfileStateOK();
 
-        if (engine.isTokenPresent(cuid)) {
-            //ToDo
-
+        if (isTokenPresent) {
+            CMS.debug("TPSProcessor.format: token exists");
+            TokenStatus newState = TokenStatus.UNINITIALIZED;
+            // Check for transition to 0/UNINITIALIZED status.
+            if(!tokenRecord.isTransitionAllowed(newState )) {
+                CMS.debug("TPSProcessor.format: token transition disallowed " +
+                        tokenRecord.getTokenStatus() +
+                        " to " + newState);
+                auditMsg = "Operation for CUID "+appletInfo.getCUIDhexString2()+
+                        " Disabled, illegal transition attempted " + tokenRecord.getTokenStatus() +
+                        " to " + newState;
+                try {
+                    tps.tdb.tdbActivity(tps, ActivityDatabase.OP_FORMAT, tokenRecord, session.getIpAddress(),
+                            auditMsg, "failure");
+                } catch (Exception ea) {
+                    auditMsg = auditMsg + ";" + " tokendb activity logging failure: " + ea;
+                }
+                throw new TPSException(auditMsg,
+                        TPSStatus.STATUS_ERROR_DISABLED_TOKEN);
+            } else {
+                CMS.debug("TPSProcessor.format: token transition allowed "+
+                        tokenRecord.getTokenStatus() +
+                        " to " + newState);
+            }
         } else {
+            CMS.debug("TPSProcessor.format: token does not exist");
+            tokenRecord.setStatus("uninitialized");
+
             checkAllowUnknownToken(TPSEngine.OP_FORMAT_PREFIX);
         }
 
@@ -953,7 +1117,7 @@ public class TPSProcessor {
 
         String appletRequiredVersion = checkForAppletUpgrade(TPSEngine.OP_FORMAT_PREFIX);
 
-        CMS.debug("TPSProcessor.format: appletVersion found: " + appletVersion + "requiredVersion: "
+        CMS.debug("TPSProcessor.format: appletVersion found: " + appletVersion + " requiredVersion: "
                 + appletRequiredVersion);
 
         SecurityLevel secLevel = SecurityLevel.SECURE_MSG_MAC_ENC;
@@ -963,7 +1127,6 @@ public class TPSProcessor {
         upgradeApplet(TPSEngine.OP_FORMAT_PREFIX, appletRequiredVersion, secLevel,
                 beginMsg.getExtensions(), tksConnId,
                 10, 90);
-
         CMS.debug("TPSProcessor.format: Completed applet upgrade.");
 
         // Add issuer info to the token
@@ -978,9 +1141,34 @@ public class TPSProcessor {
 
         SecureChannel channel = checkAndUpgradeSymKeys();
         channel.externalAuthenticate();
+        tokenRecord.setKeyInfo(channel.getKeyInfoData().toHexString2());
+
+        // Update Token DB
+        try {
+            tps.tdb.tdbUpdateTokenEntry(tps, tokenRecord);
+        } catch (Exception e){
+            auditMsg = "TPSProcessor.enroll: Failed to add token: " + e.toString();
+            try {
+                tps.tdb.tdbActivity(tps, ActivityDatabase.OP_FORMAT, tokenRecord, session.getIpAddress(),
+                    auditMsg, "failure");
+            } catch (Exception ea) {
+                auditMsg = auditMsg + ";" +" tokendb activity logging failure: "+ ea;
+            }
+            throw new TPSException(auditMsg);
+        }
 
-        // ToDo: Update Token DB
         // ToDo:  Revoke certificates
+        auditMsg = "format operation succeeded";
+
+        try {
+            tps.tdb.tdbActivity(tps, ActivityDatabase.OP_FORMAT, tokenRecord, session.getIpAddress(), auditMsg, "success");
+
+        } catch (Exception ea) {
+            auditMsg = auditMsg + ";" + " tokendb activity logging failure: " + ea;
+            //nothing to do here
+        }
+
+        CMS.debug("TPSProcessor.format:: ends");
 
     }
 
@@ -1245,9 +1433,9 @@ public class TPSProcessor {
 
         IConfigStore configStore = CMS.getConfigStore();
 
-        String appletUpdate = currentTokenOperation + "." + selectedTokenType + "."
+        String appletUpdate = "op."+ currentTokenOperation + "." + selectedTokenType + "."
                 + TPSEngine.CFG_UPDATE_APPLET_ENABLE;
-
+        CMS.debug("TPSProcessor.checkForAppletUpdateEnabled: getting config: "+ appletUpdate);
         try {
             enabled = configStore.getBoolean(appletUpdate, false);
         } catch (EBaseException e) {
@@ -1256,7 +1444,7 @@ public class TPSProcessor {
                     TPSStatus.STATUS_ERROR_UPGRADE_APPLET);
 
         }
-
+        CMS.debug("TPSProcessor.checkForAppletUpdateEnabled: returning "+ enabled);
         return enabled;
     }
 
@@ -1266,7 +1454,7 @@ public class TPSProcessor {
 
         String appletRequiredConfig = operation + "." + selectedTokenType + "."
                 + TPSEngine.CFG_APPLET_UPDATE_REQUIRED_VERSION;
-
+        CMS.debug("TPSProcessor.checkForAppletUpgrade: getting config: "+ appletRequiredConfig);
         try {
             requiredVersion = configStore.getString(appletRequiredConfig, null);
         } catch (EBaseException e) {
@@ -1290,7 +1478,7 @@ public class TPSProcessor {
 
         IConfigStore configStore = CMS.getConfigStore();
 
-        String unknownConfig = operation + "." + TPSEngine.CFG_ALLOW_UNKNOWN_TOKEN;
+        String unknownConfig = "op."+ operation + "." + TPSEngine.CFG_ALLOW_UNKNOWN_TOKEN;
 
         try {
             allow = configStore.getBoolean(unknownConfig, true);
@@ -1672,7 +1860,7 @@ public class TPSProcessor {
         result.setTotalMem(total_mem);
         result.setFreeMem(free_mem);
 
-        CMS.debug("TPSProcessor.getAppletInfo: cuid: " + result.getCUIDString() + " msn: " + result.getMSNString()
+        CMS.debug("TPSProcessor.getAppletInfo: cuid: " + result.getCUIDhexString() + " msn: " + result.getMSNString()
                 + " major version: " + result.getMinorVersion() + " minor version: " + result.getMinorVersion()
                 + " App major version: " + result.getAppMajorVersion() + " App minor version: "
                 + result.getAppMinorVersion());
@@ -1812,6 +2000,9 @@ public class TPSProcessor {
 
                 String curVersionStr = curKeyInfo.toHexString();
                 String newVersionStr = newVersion.toHexString();
+                TPSSession session = getSession();
+                TokenRecord tokenRecord = session.getTokenRecord();
+                tokenRecord.setKeyInfo(newVersion.toHexString2());
 
                 CMS.debug("TPSProcessor.checkAndUpgradeSymKeys: curVersionStr: " + curVersionStr + " newVersionStr: "
                         + newVersionStr);
diff --git a/base/tps-tomcat/src/org/dogtagpki/server/tps/rest/TokenService.java b/base/tps-tomcat/src/org/dogtagpki/server/tps/rest/TokenService.java
index e64328fc79d92b3bc5a175ebc8d97b6540f9c670..1814d1246f3423f849554d25f72706be591ed687 100644
--- a/base/tps-tomcat/src/org/dogtagpki/server/tps/rest/TokenService.java
+++ b/base/tps-tomcat/src/org/dogtagpki/server/tps/rest/TokenService.java
@@ -35,6 +35,7 @@ import javax.ws.rs.core.Response;
 import javax.ws.rs.core.UriInfo;
 
 import org.dogtagpki.server.tps.TPSSubsystem;
+import org.dogtagpki.server.tps.dbs.ActivityDatabase;
 import org.dogtagpki.server.tps.dbs.TokenDatabase;
 import org.dogtagpki.server.tps.dbs.TokenRecord;
 import org.jboss.resteasy.plugins.providers.atom.Link;
@@ -273,21 +274,37 @@ public class TokenService extends PKIService implements TokenResource {
         String tokenID = tokenData.getTokenID();
         CMS.debug("TokenService.addToken(\"" + tokenID + "\")");
 
+        String remoteUser = servletRequest.getRemoteUser();
+        String ipAddress = servletRequest.getRemoteAddr();
+
+        TPSSubsystem subsystem = (TPSSubsystem)CMS.getSubsystem(TPSSubsystem.ID);
+        TokenRecord tokenRecord = null;
         try {
-            TPSSubsystem subsystem = (TPSSubsystem)CMS.getSubsystem(TPSSubsystem.ID);
             TokenDatabase database = subsystem.getTokenDatabase();
 
             // new tokens are uninitialized when created
             tokenData.setStatus(TokenStatus.UNINITIALIZED);
 
-            database.addRecord(tokenID, createTokenRecord(tokenData));
+            tokenRecord = createTokenRecord(tokenData);
+            database.addRecord(tokenID, tokenRecord);
+            subsystem.tdb.tdbActivity(subsystem, ActivityDatabase.OP_ADD,
+                tokenRecord, ipAddress, "added token", "success",
+                remoteUser);
             tokenData = createTokenData(database.getRecord(tokenID));
 
             return createCreatedResponse(tokenData, tokenData.getLink().getHref());
 
         } catch (Exception e) {
             e.printStackTrace();
-            throw new PKIException(e.getMessage());
+            String msg = e.getMessage();
+            try {
+                subsystem.tdb.tdbActivity(subsystem, ActivityDatabase.OP_ADD,
+                    tokenRecord, ipAddress, "add token", "failure",
+                    remoteUser);
+            } catch (Exception ea) {
+                msg = msg + ";" +" tokendb activity logging failure: "+ ea;
+            }
+            throw new PKIException(msg);
         }
     }
 
@@ -299,16 +316,23 @@ public class TokenService extends PKIService implements TokenResource {
 
         CMS.debug("TokenService.replaceToken(\"" + tokenID + "\")");
 
+        String remoteUser = servletRequest.getRemoteUser();
+        String ipAddress = servletRequest.getRemoteAddr();
+
+        TPSSubsystem subsystem = (TPSSubsystem)CMS.getSubsystem(TPSSubsystem.ID);
+        TokenRecord tokenRecord = null;
         try {
-            TPSSubsystem subsystem = (TPSSubsystem)CMS.getSubsystem(TPSSubsystem.ID);
             TokenDatabase database = subsystem.getTokenDatabase();
 
-            TokenRecord tokenRecord = database.getRecord(tokenID);
-            tokenRecord.setUserID(tokenData.getUserID());
+            tokenRecord = database.getRecord(tokenID);
+            tokenRecord.setUserID(remoteUser);
             tokenRecord.setType(tokenData.getType());
             tokenRecord.setAppletID(tokenData.getAppletID());
             tokenRecord.setKeyInfo(tokenData.getKeyInfo());
             database.updateRecord(tokenID, tokenRecord);
+            subsystem.tdb.tdbActivity(subsystem, ActivityDatabase.OP_DO_TOKEN,
+                tokenRecord, ipAddress, "replaced token", "success",
+                remoteUser);
 
             tokenData = createTokenData(database.getRecord(tokenID));
 
@@ -316,7 +340,15 @@ public class TokenService extends PKIService implements TokenResource {
 
         } catch (Exception e) {
             e.printStackTrace();
-            throw new PKIException(e.getMessage());
+            String msg = e.getMessage();
+            try {
+                subsystem.tdb.tdbActivity(subsystem, ActivityDatabase.OP_DO_TOKEN,
+                    tokenRecord, ipAddress, "replace token",
+                    "failure", remoteUser);
+            } catch (Exception ea) {
+                msg = msg + ";" +" tokendb activity logging failure: "+ ea;
+            }
+            throw new PKIException(msg);
         }
     }
 
@@ -328,11 +360,15 @@ public class TokenService extends PKIService implements TokenResource {
 
         CMS.debug("TokenService.modifyToken(\"" + tokenID + "\")");
 
+        String remoteUser = servletRequest.getRemoteUser();
+        String ipAddress = servletRequest.getRemoteAddr();
+
+        TPSSubsystem subsystem = (TPSSubsystem)CMS.getSubsystem(TPSSubsystem.ID);
+        TokenRecord tokenRecord = null;
         try {
-            TPSSubsystem subsystem = (TPSSubsystem)CMS.getSubsystem(TPSSubsystem.ID);
             TokenDatabase database = subsystem.getTokenDatabase();
 
-            TokenRecord tokenRecord = database.getRecord(tokenID);
+            tokenRecord = database.getRecord(tokenID);
 
             // update user ID if specified
             String userID = tokenData.getUserID();
@@ -359,6 +395,9 @@ public class TokenService extends PKIService implements TokenResource {
             }
 
             database.updateRecord(tokenID, tokenRecord);
+            subsystem.tdb.tdbActivity(subsystem, ActivityDatabase.OP_DO_TOKEN,
+                tokenRecord, ipAddress, "modified token", "success",
+                remoteUser);
 
             tokenData = createTokenData(database.getRecord(tokenID));
 
@@ -366,7 +405,15 @@ public class TokenService extends PKIService implements TokenResource {
 
         } catch (Exception e) {
             e.printStackTrace();
-            throw new PKIException(e.getMessage());
+            String msg = e.getMessage();
+            try {
+                subsystem.tdb.tdbActivity(subsystem, ActivityDatabase.OP_DO_TOKEN,
+                    tokenRecord, ipAddress, "modify token",
+                    "failure", remoteUser);
+            } catch (Exception ea) {
+                msg = msg + ";" +" tokendb activity logging failure: "+ ea;
+            }
+            throw new PKIException(msg);
         }
     }
 
@@ -378,11 +425,15 @@ public class TokenService extends PKIService implements TokenResource {
 
         CMS.debug("TokenService.changeTokenStatus(\"" + tokenID + "\", \"" + tokenStatus + "\")");
 
+        String remoteUser = servletRequest.getRemoteUser();
+        String ipAddress = servletRequest.getRemoteAddr();
+
+        TPSSubsystem subsystem = (TPSSubsystem)CMS.getSubsystem(TPSSubsystem.ID);
+        TokenRecord tokenRecord = null;
         try {
-            TPSSubsystem subsystem = (TPSSubsystem)CMS.getSubsystem(TPSSubsystem.ID);
             TokenDatabase database = subsystem.getTokenDatabase();
 
-            TokenRecord tokenRecord = database.getRecord(tokenID);
+            tokenRecord = database.getRecord(tokenID);
             TokenStatus currentTokenStatus = getTokenStatus(tokenRecord);
             CMS.debug("TokenService.changeTokenStatus(): current status: " + currentTokenStatus);
 
@@ -391,12 +442,20 @@ public class TokenService extends PKIService implements TokenResource {
             CMS.debug("TokenService.changeTokenStatus(): allowed next statuses: " + nextStatuses);
             if (nextStatuses == null || !nextStatuses.contains(tokenStatus)) {
                 CMS.debug("TokenService.changeTokenStatus(): next status not allowed: " + tokenStatus);
+                subsystem.tdb.tdbActivity(subsystem, ActivityDatabase.OP_DO_TOKEN,
+                    tokenRecord, ipAddress,
+                    "change token status not allowed",
+                    "failure", remoteUser);
                 throw new BadRequestException("Invalid token status transition: " + currentTokenStatus + " to " + tokenStatus);
             }
 
             CMS.debug("TokenService.changeTokenStatus(): next status allowed: " + tokenStatus);
             setTokenStatus(tokenRecord, tokenStatus);
             database.updateRecord(tokenID, tokenRecord);
+            String msg = "changed token status to "+ tokenStatus;
+            subsystem.tdb.tdbActivity(subsystem, ActivityDatabase.OP_DO_TOKEN,
+                tokenRecord, ipAddress, msg,
+                "success", remoteUser);
 
             TokenData tokenData = createTokenData(database.getRecord(tokenID));
 
@@ -404,7 +463,16 @@ public class TokenService extends PKIService implements TokenResource {
 
         } catch (Exception e) {
             e.printStackTrace();
-            throw new PKIException(e.getMessage());
+            String msg = e.getMessage();
+            String msg2 = "change token status to " + tokenStatus;
+            try {
+                subsystem.tdb.tdbActivity(subsystem, ActivityDatabase.OP_DO_TOKEN,
+                    tokenRecord, ipAddress, msg2,
+                    "failure", remoteUser);
+            } catch (Exception ea) {
+                msg = msg + ";" +" tokendb activity logging failure: "+ ea;
+            }
+            throw new PKIException(msg);
         }
     }
 
@@ -415,16 +483,32 @@ public class TokenService extends PKIService implements TokenResource {
 
         CMS.debug("TokenService.removeToken(\"" + tokenID + "\")");
 
+        String remoteUser = servletRequest.getRemoteUser();
+        String ipAddress = servletRequest.getRemoteAddr();
+
+        TPSSubsystem subsystem = (TPSSubsystem)CMS.getSubsystem(TPSSubsystem.ID);
+        TokenRecord tokenRecord = null;
         try {
-            TPSSubsystem subsystem = (TPSSubsystem)CMS.getSubsystem(TPSSubsystem.ID);
             TokenDatabase database = subsystem.getTokenDatabase();
+            tokenRecord = database.getRecord(tokenID);
             database.removeRecord(tokenID);
+            subsystem.tdb.tdbActivity(subsystem, ActivityDatabase.OP_DELETE,
+                tokenRecord, ipAddress, "removed token", "success",
+                remoteUser);
 
             return createNoContentResponse();
 
         } catch (Exception e) {
             e.printStackTrace();
-            throw new PKIException(e.getMessage());
+            String msg = e.getMessage();
+            try {
+                subsystem.tdb.tdbActivity(subsystem, ActivityDatabase.OP_DELETE,
+                    tokenRecord, ipAddress, "remove token",
+                    "failure", remoteUser);
+            } catch (Exception ea) {
+                msg = msg + ";" +" tokendb activity logging failure: "+ ea;
+            }
+            throw new PKIException(msg);
         }
     }
 }
-- 
1.8.4.2

