Skip to content

Commit

Permalink
again fix protection of NESTED responses
Browse files Browse the repository at this point in the history
  • Loading branch information
Akretsch committed Jul 10, 2024
1 parent b9d51f3 commit 35b2465
Show file tree
Hide file tree
Showing 3 changed files with 112 additions and 99 deletions.
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
<groupId>com.siemens.pki</groupId>
<artifactId>CmpRaComponent</artifactId>
<packaging>jar</packaging>
<version>4.1.3</version>
<version>4.1.4</version>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<parent.basedir>.</parent.basedir>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -177,19 +177,6 @@ protected CmsEncryptorBase buildEncryptor(
return new KeyTransportEncryptor(ckgConfiguration, recipientCert, initialRequestType, interfaceName);
}

private MsgOutputProtector getOutputProtector(final PersistencyContext persistencyContext, final int bodyType)
throws Exception {
return new MsgOutputProtector(
ConfigLogger.log(
INTERFACE_NAME,
"Configuration.getDownstreamConfiguration",
config::getDownstreamConfiguration,
persistencyContext.getCertProfile(),
bodyType),
INTERFACE_NAME,
persistencyContext);
}

/**
* special handling for CR, IR, KUR
*
Expand Down Expand Up @@ -395,7 +382,7 @@ PKIMessage handleInputMessage(final PKIMessage in) {
try {
try {
byte[] transactionId =
ifNotNull(in, m -> m.getHeader().getTransactionID().getEncoded());
ifNotNull(in, m -> m.getHeader().getTransactionID().getOctets());
if (transactionId == null) {
MsgOutputProtector protector = new MsgOutputProtector(
ConfigLogger.log(
Expand All @@ -411,14 +398,37 @@ PKIMessage handleInputMessage(final PKIMessage in) {
PkiMessageGenerator.generateErrorBody(
PKIFailureInfo.badDataFormat, "transactionId missing"));
}
persistencyContext = persistencyContextManager.loadCreatePersistencyContext(
in.getHeader().getTransactionID().getOctets());
persistencyContext = persistencyContextManager.loadCreatePersistencyContext(transactionId);
final int inBodyType = in.getBody().getType();
if (inBodyType == PKIBody.TYPE_NESTED) {
try {
return handleNestedRequest(in, persistencyContext);
} finally {
// suppress persistency update for NESTED messages
persistencyContext = null;
}
}
final InputValidator inputValidator = new InputValidator(
INTERFACE_NAME,
config::getDownstreamConfiguration,
config::isRaVerifiedAcceptable,
supportedMessageTypes,
persistencyContext);
inputValidator.validate(in);

PKIMessage responseFromUpstream = handleInputRequest(in, persistencyContext);
PKIMessage responseFromUpstream = handleValidatedRequest(in, persistencyContext);
// apply downstream protection and nesting
List<CMPCertificate> issuingChain = null;
responseBodyType = responseFromUpstream.getBody().getType();
switch (responseBodyType) {
case PKIBody.TYPE_NESTED:
// never nest a nested message
try {
return responseFromUpstream;
} finally {
// suppress persistency update for NESTED messages
persistencyContext = null;
}
case PKIBody.TYPE_INIT_REP:
case PKIBody.TYPE_CERT_REP:
case PKIBody.TYPE_KEY_UPDATE_REP:
Expand All @@ -432,8 +442,14 @@ PKIMessage handleInputMessage(final PKIMessage in) {
break;
default:
}

PKIMessage protectedResponse = getOutputProtector(persistencyContext, responseBodyType)
final CmpMessageInterface downstreamConfiguration = ConfigLogger.log(
INTERFACE_NAME,
"Configuration.getDownstreamConfiguration",
config::getDownstreamConfiguration,
persistencyContext.getCertProfile(),
responseBodyType);
PKIMessage protectedResponse = new MsgOutputProtector(
downstreamConfiguration, INTERFACE_NAME, persistencyContext)
.protectOutgoingMessage(
new PKIMessage(
responseFromUpstream.getHeader(),
Expand All @@ -445,12 +461,7 @@ PKIMessage handleInputMessage(final PKIMessage in) {
// never nest a nested message
return protectedResponse;
}
final CmpMessageInterface downstreamConfiguration = ConfigLogger.log(
INTERFACE_NAME,
"Configuration.getDownstreamConfiguration",
config::getDownstreamConfiguration,
null,
responseBodyType);

final NestedEndpointContext nestedEndpointContext = ConfigLogger.logOptional(
INTERFACE_NAME,
"CmpMessageInterface.getNestedEndpointContext()",
Expand All @@ -465,11 +476,23 @@ PKIMessage handleInputMessage(final PKIMessage in) {
new PKIBody(PKIBody.TYPE_NESTED, new PKIMessages(protectedResponse)));
} catch (final BaseCmpException e) {
final PKIBody errorBody = e.asErrorBody();
return getOutputProtector(persistencyContext, responseBodyType)
final CmpMessageInterface downstreamConfiguration = ConfigLogger.log(
INTERFACE_NAME,
"Configuration.getDownstreamConfiguration",
config::getDownstreamConfiguration,
persistencyContext.getCertProfile(),
errorBody.getType());
return new MsgOutputProtector(downstreamConfiguration, INTERFACE_NAME, persistencyContext)
.generateAndProtectResponseTo(in, errorBody);
} catch (final RuntimeException ex) {
final PKIBody errorBody = new CmpProcessingException(INTERFACE_NAME, ex).asErrorBody();
return getOutputProtector(persistencyContext, responseBodyType)
final CmpMessageInterface downstreamConfiguration = ConfigLogger.log(
INTERFACE_NAME,
"Configuration.getDownstreamConfiguration",
config::getDownstreamConfiguration,
persistencyContext.getCertProfile(),
errorBody.getType());
return new MsgOutputProtector(downstreamConfiguration, INTERFACE_NAME, persistencyContext)
.generateAndProtectResponseTo(in, errorBody);
} finally {
if (persistencyContext != null) {
Expand All @@ -493,71 +516,59 @@ PKIMessage handleInputMessage(final PKIMessage in) {
}
}

private PKIMessage handleInputRequest(final PKIMessage in, final PersistencyContext persistencyContext)
throws Exception {

final int inBodyType = in.getBody().getType();
if (inBodyType == PKIBody.TYPE_NESTED) {
final CmpMessageInterface downstreamConfiguration = ConfigLogger.log(
INTERFACE_NAME,
"Configuration.getDownstreamConfiguration",
config::getDownstreamConfiguration,
null,
PKIBody.TYPE_NESTED);
final NestedEndpointContext nestedEndpointContext = ConfigLogger.logOptional(
INTERFACE_NAME,
"CmpMessageInterface.getNestedEndpointContext()",
downstreamConfiguration::getNestedEndpointContext);
if (nestedEndpointContext != null) {
final MessageHeaderValidator nestedHeaderValidator = new MessageHeaderValidator(NESTED_INTERFACE_NAME);
nestedHeaderValidator.validate(in);
final ProtectionValidator nestedProtectionValidator = new ProtectionValidator(
NESTED_INTERFACE_NAME,
ConfigLogger.logOptional(
NESTED_INTERFACE_NAME,
"NestedEndpointContext.getInputVerification()",
nestedEndpointContext::getInputVerification));
nestedProtectionValidator.validate(in);
PKIHeader inHeader = in.getHeader();
boolean isIncomingRecipientValid = ConfigLogger.log(
NESTED_INTERFACE_NAME,
"NestedEndpointContext.isIncomingRecipientValid()",
() -> nestedEndpointContext.isIncomingRecipientValid(
inHeader.getRecipient().getName().toString()));
if (!isIncomingRecipientValid) {
return upstreamHandler.handleRequest(in, persistencyContext);
}
final PKIMessage[] embeddedMessages =
PKIMessages.getInstance(in.getBody().getContent()).toPKIMessageArray();
if (embeddedMessages == null || embeddedMessages.length == 0) {
throw new CmpProcessingException(
private PKIMessage handleNestedRequest(final PKIMessage in, final PersistencyContext persistencyContext)
throws BaseCmpException, CmpProcessingException, GeneralSecurityException, Exception {
final CmpMessageInterface downstreamConfiguration = ConfigLogger.log(
INTERFACE_NAME,
"Configuration.getDownstreamConfiguration",
config::getDownstreamConfiguration,
null,
PKIBody.TYPE_NESTED);
final NestedEndpointContext nestedEndpointContext = ConfigLogger.logOptional(
INTERFACE_NAME,
"CmpMessageInterface.getNestedEndpointContext()",
downstreamConfiguration::getNestedEndpointContext);
if (nestedEndpointContext != null) {
final MessageHeaderValidator nestedHeaderValidator = new MessageHeaderValidator(NESTED_INTERFACE_NAME);
nestedHeaderValidator.validate(in);
final ProtectionValidator nestedProtectionValidator = new ProtectionValidator(
NESTED_INTERFACE_NAME,
ConfigLogger.logOptional(
NESTED_INTERFACE_NAME,
PKIFailureInfo.badMessageCheck,
"no embedded messages inside NESTED message");
}
// wrapped protection case
if (embeddedMessages.length == 1) {
return handleInputMessage(embeddedMessages[0]);
}
// batching
final PKIMessage[] responses = Arrays.stream(embeddedMessages)
.map(this::handleInputMessage)
.toArray(PKIMessage[]::new);
// batched responses needs to be wrapped in a new NESTED response
MsgOutputProtector nestedOutputProtector =
new MsgOutputProtector(nestedEndpointContext, INTERFACE_NAME);
return nestedOutputProtector.generateAndProtectResponseTo(
in, new PKIBody(PKIBody.TYPE_NESTED, new PKIMessages(responses)));
"NestedEndpointContext.getInputVerification()",
nestedEndpointContext::getInputVerification));
nestedProtectionValidator.validate(in);
PKIHeader inHeader = in.getHeader();
boolean isIncomingRecipientValid = ConfigLogger.log(
NESTED_INTERFACE_NAME,
"NestedEndpointContext.isIncomingRecipientValid()",
() -> nestedEndpointContext.isIncomingRecipientValid(
inHeader.getRecipient().getName().toString()));
if (!isIncomingRecipientValid) {
return upstreamHandler.handleRequest(in, persistencyContext);
}
final PKIMessage[] embeddedMessages =
PKIMessages.getInstance(in.getBody().getContent()).toPKIMessageArray();
if (embeddedMessages == null || embeddedMessages.length == 0) {
throw new CmpProcessingException(
NESTED_INTERFACE_NAME,
PKIFailureInfo.badMessageCheck,
"no embedded messages inside NESTED message");
}
// wrapped protection case
if (embeddedMessages.length == 1) {
return handleInputMessage(embeddedMessages[0]);
}
// batching
final PKIMessage[] responses = Arrays.stream(embeddedMessages)
.map(this::handleInputMessage)
.toArray(PKIMessage[]::new);
// batched responses needs to be wrapped in a new NESTED response
MsgOutputProtector nestedOutputProtector = new MsgOutputProtector(nestedEndpointContext, INTERFACE_NAME);
return nestedOutputProtector.generateAndProtectResponseTo(
in, new PKIBody(PKIBody.TYPE_NESTED, new PKIMessages(responses)));
}
final InputValidator inputValidator = new InputValidator(
INTERFACE_NAME,
config::getDownstreamConfiguration,
config::isRaVerifiedAcceptable,
supportedMessageTypes,
persistencyContext);
inputValidator.validate(in);
return handleValidatedRequest(in, persistencyContext);
return upstreamHandler.handleRequest(in, persistencyContext);
}

private PKIMessage handleP10CertificateRequest(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -189,15 +189,17 @@ private void assertValueNotNull(final Object value, final int failInfo, final St
@Override
public String validate(final PKIMessage message) throws BaseCmpException {
try {
final ASN1GeneralizedTime messageTime = message.getHeader().getMessageTime();
if (messageTime != null) {
final long diffInMillis = messageTime.getDate().getTime() - new Date().getTime();
if (!ConfigLogger.log(
interfaceName,
"CmpMessageInterface.isMessageTimeDeviationAllowed(long)",
() -> cmpInterfaceConfig.isMessageTimeDeviationAllowed(diffInMillis / 1000L))) {
throw new CmpValidationException(
interfaceName, PKIFailureInfo.badTime, "message time out of allowed range");
if (cmpInterfaceConfig != null) {
final ASN1GeneralizedTime messageTime = message.getHeader().getMessageTime();
if (messageTime != null) {
final long diffInMillis = messageTime.getDate().getTime() - new Date().getTime();
if (!ConfigLogger.log(
interfaceName,
"CmpMessageInterface.isMessageTimeDeviationAllowed(long)",
() -> cmpInterfaceConfig.isMessageTimeDeviationAllowed(diffInMillis / 1000L))) {
throw new CmpValidationException(
interfaceName, PKIFailureInfo.badTime, "message time out of allowed range");
}
}
}

Expand Down

0 comments on commit 35b2465

Please sign in to comment.