summaryrefslogtreecommitdiffstats
path: root/base/tps/src
diff options
context:
space:
mode:
authorEndi S. Dewata <edewata@redhat.com>2016-05-25 06:27:46 +0200
committerEndi S. Dewata <edewata@redhat.com>2016-06-03 01:48:09 +0200
commita8e71fb5aedd74a0822d3211d1cd08e0b5af3684 (patch)
tree005a9a40277f9291099c1fc6ce971905cb6ffd8b /base/tps/src
parent525faaf6aec4467267d6add92bf0d5427d20307b (diff)
downloadpki-a8e71fb5aedd74a0822d3211d1cd08e0b5af3684.tar.gz
pki-a8e71fb5aedd74a0822d3211d1cd08e0b5af3684.tar.xz
pki-a8e71fb5aedd74a0822d3211d1cd08e0b5af3684.zip
Added TPS token state transition validation.
The TPSSubsystem has been modified to load and validate the token state transition lists during initialization. If any of the lists is empty or any of the transitions is invalid, the initialization will fail and the subsystem will not start. https://fedorahosted.org/pki/ticket/2334
Diffstat (limited to 'base/tps/src')
-rw-r--r--base/tps/src/org/dogtagpki/server/tps/TPSSubsystem.java128
-rw-r--r--base/tps/src/org/dogtagpki/server/tps/TPSTokendb.java2
-rw-r--r--base/tps/src/org/dogtagpki/server/tps/engine/TPSEngine.java51
-rw-r--r--base/tps/src/org/dogtagpki/server/tps/processor/TPSEnrollProcessor.java2
-rw-r--r--base/tps/src/org/dogtagpki/server/tps/processor/TPSProcessor.java6
-rw-r--r--base/tps/src/org/dogtagpki/server/tps/rest/TokenService.java20
6 files changed, 127 insertions, 82 deletions
diff --git a/base/tps/src/org/dogtagpki/server/tps/TPSSubsystem.java b/base/tps/src/org/dogtagpki/server/tps/TPSSubsystem.java
index 2d415c16c..ea765da02 100644
--- a/base/tps/src/org/dogtagpki/server/tps/TPSSubsystem.java
+++ b/base/tps/src/org/dogtagpki/server/tps/TPSSubsystem.java
@@ -22,6 +22,7 @@ import java.util.HashMap;
import java.util.LinkedHashSet;
import java.util.Map;
+import org.apache.commons.lang.StringUtils;
import org.dogtagpki.server.tps.authentication.AuthenticationManager;
import org.dogtagpki.server.tps.cms.ConnectionManager;
import org.dogtagpki.server.tps.config.AuthenticatorDatabase;
@@ -36,6 +37,7 @@ import org.dogtagpki.server.tps.dbs.TokenDatabase;
import org.dogtagpki.server.tps.dbs.TokenRecord;
import org.dogtagpki.server.tps.engine.TPSEngine;
import org.dogtagpki.server.tps.mapping.MappingResolverManager;
+import org.dogtagpki.tps.main.TPSException;
import org.mozilla.jss.CryptoManager;
import org.mozilla.jss.CryptoManager.NotInitializedException;
import org.mozilla.jss.crypto.ObjectNotFoundException;
@@ -51,6 +53,7 @@ import com.netscape.certsrv.logging.ILogger;
import com.netscape.certsrv.request.IRequestListener;
import com.netscape.certsrv.request.IRequestQueue;
import com.netscape.certsrv.tps.token.TokenStatus;
+import com.netscape.cmscore.base.FileConfigStore;
import com.netscape.cmscore.dbs.DBSubsystem;
/**
@@ -81,7 +84,9 @@ public class TPSSubsystem implements IAuthority, ISubsystem {
public TPSEngine engine;
public TPSTokendb tdb;
- public Map<TokenStatus, Collection<TokenStatus>> allowedTransitions = new HashMap<TokenStatus, Collection<TokenStatus>>();
+
+ public Map<TokenStatus, Collection<TokenStatus>> uiTransitions;
+ public Map<TokenStatus, Collection<TokenStatus>> operationTransitions;
@Override
public String getId() {
@@ -116,45 +121,109 @@ public class TPSSubsystem implements IAuthority, ISubsystem {
profileDatabase = new ProfileDatabase();
profileMappingDatabase = new ProfileMappingDatabase();
- CMS.debug("TokenSubsystem: allowed transitions:");
+ FileConfigStore defaultConfig = new FileConfigStore("/usr/share/pki/tps/conf/CS.cfg");
+
+ uiTransitions = loadAndValidateTokenStateTransitions(
+ defaultConfig, cs, TPSEngine.CFG_TOKENDB_ALLOWED_TRANSITIONS);
+
+ operationTransitions = loadAndValidateTokenStateTransitions(
+ defaultConfig, cs, TPSEngine.CFG_OPERATIONS_ALLOWED_TRANSITIONS);
+
+ tdb = new TPSTokendb(this);
+
+ engine = new TPSEngine();
+ engine.init();
+ }
+
+ public Map<TokenStatus, Collection<TokenStatus>> loadTokenStateTransitions(IConfigStore cs, String property) throws EBaseException {
+
+ String value = cs.getString(property);
- // initialize allowed token state transitions with empty containers
+ if (StringUtils.isEmpty(value)) {
+ CMS.debug("Missing token state transitions in " + property);
+ throw new EBaseException("Missing token state transition in " + property);
+ }
+
+ Map<TokenStatus, Collection<TokenStatus>> transitions = new HashMap<TokenStatus, Collection<TokenStatus>>();
+
+ // initialize list with empty containers
for (TokenStatus state : TokenStatus.values()) {
- allowedTransitions.put(state, new LinkedHashSet<TokenStatus>());
+ transitions.put(state, new LinkedHashSet<TokenStatus>());
}
- // load allowed token state transitions from TPS configuration
- for (String transition : cs.getString(TPSEngine.CFG_TOKENDB_ALLOWED_TRANSITIONS).split(",")) {
+ for (String transition : value.split(",")) {
+
String states[] = transition.split(":");
+ if (states.length < 2) {
+ CMS.debug("Invalid token state transition in " + property + ": " + transition);
+ throw new EBaseException("Invalid token state transition in " + property + ": " + transition);
+ }
- TokenStatus fromState = TokenStatus.fromInt(Integer.valueOf(states[0]));
- TokenStatus toState = TokenStatus.fromInt(Integer.valueOf(states[1]));
- CMS.debug("TokenSubsystem: - " + fromState + " to " + toState);
+ TokenStatus currentState = TokenStatus.fromInt(Integer.valueOf(states[0]));
+ TokenStatus nextState = TokenStatus.fromInt(Integer.valueOf(states[1]));
- Collection<TokenStatus> nextStates = allowedTransitions.get(fromState);
- nextStates.add(toState);
+ String info = currentState + " to " + nextState +
+ " (" + currentState.getValue() + ":" + nextState.getValue() + ")";
+ CMS.debug("TokenSubsystem: - " + info);
+
+ Collection<TokenStatus> nextStates = transitions.get(currentState);
+ nextStates.add(nextState);
}
- tdb = new TPSTokendb(this);
+ return transitions;
+ }
- engine = new TPSEngine();
- engine.init();
+ public void validateTokenStateTransitions(
+ Map<TokenStatus, Collection<TokenStatus>> defaultConfig,
+ Map<TokenStatus, Collection<TokenStatus>> userConfig) throws EBaseException {
+ for (TokenStatus currentState : userConfig.keySet()) {
+ Collection<TokenStatus> nextStates = userConfig.get(currentState);
+ Collection<TokenStatus> defaultNextStates = defaultConfig.get(currentState);
+
+ for (TokenStatus nextState : nextStates) {
+ if (!defaultNextStates.contains(nextState)) {
+ String info = currentState + " to " + nextState +
+ " (" + currentState.getValue() + ":" + nextState.getValue() + ")";
+ throw new EBaseException("Unsupported token state transition: " + info);
+ }
+ }
+ }
}
+ public Map<TokenStatus, Collection<TokenStatus>> loadAndValidateTokenStateTransitions(
+ IConfigStore defaultConfig,
+ IConfigStore userDefinedConfig,
+ String property) throws EBaseException {
+
+ CMS.debug("TokenSubsystem: Loading transitions in " + property);
+
+ CMS.debug("TokenSubsystem: * default transitions:");
+ Map<TokenStatus, Collection<TokenStatus>> defaultTransitions =
+ loadTokenStateTransitions(defaultConfig, property);
+
+ CMS.debug("TokenSubsystem: * user-defined transitions:");
+ Map<TokenStatus, Collection<TokenStatus>> userDefinedTransitions =
+ loadTokenStateTransitions(userDefinedConfig, property);
+
+ CMS.debug("TokenSubsystem: Validating transitions in " + property);
+ validateTokenStateTransitions(defaultTransitions, userDefinedTransitions);
+
+ return userDefinedTransitions;
+ }
/**
- * Return the allowed next states for a given token based on TPS configuration.
+ * Return the allowed next states for changing token state via Web UI or CLI.
*
- * If the current state is SUSPENDED, token will be allowed transition to either
- * FORMATTED or ACTIVE depending on whether the token has certificates.
+ * If the current state is SUSPENDED, token will be allowed to transition to
+ * either FORMATTED or ACTIVE depending on whether the token has certificates.
*
* @param tokenRecord
* @return A non-null collection of allowed next token states.
*/
- public Collection<TokenStatus> getNextTokenStates(TokenRecord tokenRecord) throws Exception {
+ public Collection<TokenStatus> getUINextTokenStates(TokenRecord tokenRecord) throws TPSException {
TokenStatus currentState = tokenRecord.getTokenStatus();
- Collection<TokenStatus> nextStates = allowedTransitions.get(currentState);
+ Collection<TokenStatus> nextStates = uiTransitions.get(currentState);
if (currentState == TokenStatus.SUSPENDED) {
@@ -180,6 +249,17 @@ public class TPSSubsystem implements IAuthority, ISubsystem {
return nextStates;
}
+ /**
+ * Return the allowed next states for TPS token operations (i.e. format and enrollment).
+ *
+ * @param tokenRecord
+ * @return A non-null collection of allowed next token states.
+ */
+ public Collection<TokenStatus> getOperationNextTokenStates(TokenRecord tokenRecord) {
+ TokenStatus currentState = tokenRecord.getTokenStatus();
+ return operationTransitions.get(currentState);
+ }
+
@Override
public void startup() throws EBaseException {
CMS.debug("TPSSubsystem: startup() begins");
@@ -296,4 +376,14 @@ public class TPSSubsystem implements IAuthority, ISubsystem {
public TPSEngine getEngine() {
return engine;
}
+
+ public boolean isUITransitionAllowed(TokenRecord tokenRecord, TokenStatus nextState) throws Exception {
+ Collection<TokenStatus> nextStates = getUINextTokenStates(tokenRecord);
+ return nextStates.contains(nextState);
+ }
+
+ public boolean isOperationTransitionAllowed(TokenRecord tokenRecord, TokenStatus nextState) {
+ Collection<TokenStatus> nextStates = getOperationNextTokenStates(tokenRecord);
+ return nextStates.contains(nextState);
+ }
}
diff --git a/base/tps/src/org/dogtagpki/server/tps/TPSTokendb.java b/base/tps/src/org/dogtagpki/server/tps/TPSTokendb.java
index 7997cc579..ed7e022fa 100644
--- a/base/tps/src/org/dogtagpki/server/tps/TPSTokendb.java
+++ b/base/tps/src/org/dogtagpki/server/tps/TPSTokendb.java
@@ -64,7 +64,7 @@ public class TPSTokendb {
TokenStatus currentTokenStatus = tokenRecord.getTokenStatus();
CMS.debug("TokenRecord.isTransitionAllowed(): current status: " + currentTokenStatus);
- Collection<TokenStatus> nextStatuses = tps.getNextTokenStates(tokenRecord);
+ Collection<TokenStatus> nextStatuses = tps.getUINextTokenStates(tokenRecord);
CMS.debug("TokenRecord.isTransitionAllowed(): allowed next statuses: " + nextStatuses);
if (!nextStatuses.contains(newState)) {
diff --git a/base/tps/src/org/dogtagpki/server/tps/engine/TPSEngine.java b/base/tps/src/org/dogtagpki/server/tps/engine/TPSEngine.java
index a577a7619..a5fbc3b7d 100644
--- a/base/tps/src/org/dogtagpki/server/tps/engine/TPSEngine.java
+++ b/base/tps/src/org/dogtagpki/server/tps/engine/TPSEngine.java
@@ -37,8 +37,6 @@ import org.dogtagpki.tps.msg.EndOpMsg.TPSStatus;
import com.netscape.certsrv.apps.CMS;
import com.netscape.certsrv.base.EBaseException;
-import com.netscape.certsrv.base.IConfigStore;
-import com.netscape.certsrv.tps.token.TokenStatus;
public class TPSEngine {
@@ -195,8 +193,6 @@ public class TPSEngine {
public static final String ENROLL_MODE_RECOVERY = RECOVERY_OP;
public static final String ERNOLL_MODE_RENEWAL = RENEWAL_OP;
- private static String transitionList;
-
public void init() {
//ToDo
}
@@ -589,51 +585,4 @@ public class TPSEngine {
return resp;
}
-
- //Check to see if special operations transition is allowed
-
- public boolean isOperationTransitionAllowed(TokenStatus oldState, TokenStatus newState) throws TPSException {
- boolean allowed = true;
-
- if (transitionList == null) {
-
- IConfigStore configStore = CMS.getConfigStore();
-
- String transConfig = CFG_OPERATIONS_ALLOWED_TRANSITIONS;
-
- CMS.debug("TPSEngine.isOperationTransistionAllowed: getting config: " + transConfig);
- try {
- transitionList = configStore.getString(transConfig, null);
- } catch (EBaseException e) {
- throw new TPSException(
- "TPSProcessor.isOperationTransitionAllowed: Internal error getting config value for operations transition list!",
- TPSStatus.STATUS_ERROR_MISCONFIGURATION);
- }
-
- if (transitionList == null) {
- throw new TPSException(
- "TPSProcessor.isOperationTransitionAllowed: Can't find non null config value for operations transition list!",
- TPSStatus.STATUS_ERROR_MISCONFIGURATION);
- }
-
- CMS.debug("TPSEngine.isOperationTransistionAllowed: transitionList is: " + transitionList);
-
- }
-
- String transition = oldState.getValue() + ":" + newState.getValue();
-
- CMS.debug("TPSEngine.isOperationTransistionAllowed: checking for transition: " + transition);
-
- if (transitionList.indexOf(transition) == -1) {
- CMS.debug("TPSEngine.isOperationTransistionAllowed: checking for transition: " + transition);
- allowed = false;
- }
-
- CMS.debug("TPSEngine.isOperationTransistionAllowed: checking for transition: " + transition + " allowed: "
- + allowed);
-
- return allowed;
-
- }
-
}
diff --git a/base/tps/src/org/dogtagpki/server/tps/processor/TPSEnrollProcessor.java b/base/tps/src/org/dogtagpki/server/tps/processor/TPSEnrollProcessor.java
index bbdc15b86..66407e3a3 100644
--- a/base/tps/src/org/dogtagpki/server/tps/processor/TPSEnrollProcessor.java
+++ b/base/tps/src/org/dogtagpki/server/tps/processor/TPSEnrollProcessor.java
@@ -282,7 +282,7 @@ public class TPSEnrollProcessor extends TPSProcessor {
TokenStatus newState = TokenStatus.ACTIVE;
// Check for transition to ACTIVE status.
- if (!tps.engine.isOperationTransitionAllowed(tokenRecord.getTokenStatus(), newState)) {
+ if (!tps.isOperationTransitionAllowed(tokenRecord, newState)) {
CMS.debug(method + " token transition disallowed " +
tokenRecord.getTokenStatus() +
" to " + newState);
diff --git a/base/tps/src/org/dogtagpki/server/tps/processor/TPSProcessor.java b/base/tps/src/org/dogtagpki/server/tps/processor/TPSProcessor.java
index aa2f24260..e8608c487 100644
--- a/base/tps/src/org/dogtagpki/server/tps/processor/TPSProcessor.java
+++ b/base/tps/src/org/dogtagpki/server/tps/processor/TPSProcessor.java
@@ -33,8 +33,6 @@ import java.util.List;
import java.util.Map;
import java.util.Set;
-import netscape.security.x509.RevocationReason;
-
import org.dogtagpki.server.tps.TPSSession;
import org.dogtagpki.server.tps.TPSSubsystem;
import org.dogtagpki.server.tps.authentication.AuthUIParameter;
@@ -98,6 +96,8 @@ import com.netscape.certsrv.tps.token.TokenStatus;
import com.netscape.cms.servlet.tks.SecureChannelProtocol;
import com.netscape.symkey.SessionKey;
+import netscape.security.x509.RevocationReason;
+
public class TPSProcessor {
public static final int RESULT_NO_ERROR = 0;
@@ -2088,7 +2088,7 @@ public class TPSProcessor {
TokenStatus newState = TokenStatus.FORMATTED;
// Check for transition to FORMATTED status.
- if (!tps.engine.isOperationTransitionAllowed(tokenRecord.getTokenStatus(), newState)) {
+ if (!tps.isOperationTransitionAllowed(tokenRecord, newState)) {
String info = " illegal transition attempted: " + tokenRecord.getTokenStatus() +
" to " + newState;
CMS.debug("TPSProcessor.format: token transition: " + info);
diff --git a/base/tps/src/org/dogtagpki/server/tps/rest/TokenService.java b/base/tps/src/org/dogtagpki/server/tps/rest/TokenService.java
index 40022a440..1c4285ed7 100644
--- a/base/tps/src/org/dogtagpki/server/tps/rest/TokenService.java
+++ b/base/tps/src/org/dogtagpki/server/tps/rest/TokenService.java
@@ -25,6 +25,7 @@ import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
+import java.util.MissingResourceException;
import java.util.ResourceBundle;
import javax.servlet.http.HttpServletRequest;
@@ -185,15 +186,23 @@ public class TokenService extends PKIService implements TokenResource {
TokenStatus status = tokenRecord.getTokenStatus();
TokenStatusData statusData = new TokenStatusData();
statusData.name = status;
- statusData.label = labels.getString(status.toString());
+ try {
+ statusData.label = labels.getString(status.toString());
+ } catch (MissingResourceException e) {
+ statusData.label = status.toString();
+ }
tokenData.setStatus(statusData);
- Collection<TokenStatus> nextStates = subsystem.getNextTokenStates(tokenRecord);
+ Collection<TokenStatus> nextStates = subsystem.getUINextTokenStates(tokenRecord);
Collection<TokenStatusData> nextStatesData = new ArrayList<TokenStatusData>();
for (TokenStatus nextState : nextStates) {
TokenStatusData nextStateData = new TokenStatusData();
nextStateData.name = nextState;
- nextStateData.label = labels.getString(status + "." + nextState);
+ try {
+ nextStateData.label = labels.getString(status + "." + nextState);
+ } catch (MissingResourceException e) {
+ nextStateData.label = nextState.toString();
+ }
nextStatesData.add(nextStateData);
}
tokenData.setNextStates(nextStatesData);
@@ -646,10 +655,7 @@ public class TokenService extends PKIService implements TokenResource {
msg = msg + " from " + currentTokenStatus + " to " + tokenStatus;
// make sure transition is allowed
- Collection<TokenStatus> nextStatuses = subsystem.getNextTokenStates(tokenRecord);
- CMS.debug("TokenService.changeTokenStatus(): allowed next statuses: " + nextStatuses);
-
- if (!nextStatuses.contains(tokenStatus)) {
+ if (!subsystem.isUITransitionAllowed(tokenRecord, tokenStatus)) {
CMS.debug("TokenService.changeTokenStatus(): next status not allowed: " + tokenStatus);
Exception ex = new BadRequestException("Invalid token status transition");
auditTokenStateChange(ILogger.FAILURE, oldStatus,