use of org.eclipse.milo.opcua.stack.core.channel.ChannelSecurity.SecurityKeys in project milo by eclipse.
the class UascServerAsymmetricHandler method openSecureChannel.
private OpenSecureChannelResponse openSecureChannel(ChannelHandlerContext ctx, OpenSecureChannelRequest request) throws UaException {
SecurityTokenRequestType requestType = request.getRequestType();
if (requestType == SecurityTokenRequestType.Issue) {
secureChannel.setMessageSecurityMode(request.getSecurityMode());
String endpointUrl = ctx.channel().attr(UascServerHelloHandler.ENDPOINT_URL_KEY).get();
EndpointDescription endpoint = stackServer.getEndpointDescriptions().stream().filter(e -> {
boolean transportMatch = Objects.equals(e.getTransportProfileUri(), transportProfile.getUri());
boolean pathMatch = Objects.equals(EndpointUtil.getPath(e.getEndpointUrl()), EndpointUtil.getPath(endpointUrl));
boolean securityPolicyMatch = Objects.equals(e.getSecurityPolicyUri(), secureChannel.getSecurityPolicy().getUri());
boolean securityModeMatch = Objects.equals(e.getSecurityMode(), request.getSecurityMode());
return transportMatch && pathMatch && securityPolicyMatch && securityModeMatch;
}).findFirst().orElseThrow(() -> {
String message = String.format("no matching endpoint found: transportProfile=%s, " + "endpointUrl=%s, securityPolicy=%s, securityMode=%s", transportProfile, endpointUrl, secureChannel.getSecurityPolicy(), request.getSecurityMode());
return new UaException(StatusCodes.Bad_SecurityChecksFailed, message);
});
ctx.channel().attr(ENDPOINT_KEY).set(endpoint);
}
if (requestType == SecurityTokenRequestType.Renew && secureChannel.getMessageSecurityMode() != request.getSecurityMode()) {
throw new UaException(StatusCodes.Bad_SecurityChecksFailed, "secure channel renewal requested a different MessageSecurityMode.");
}
long channelLifetime = request.getRequestedLifetime().longValue();
channelLifetime = Math.min(channelLifetime, stackServer.getConfig().getMaximumSecureChannelLifetime().longValue());
channelLifetime = Math.max(channelLifetime, stackServer.getConfig().getMinimumSecureChannelLifetime().longValue());
ChannelSecurityToken newToken = new ChannelSecurityToken(uint(secureChannel.getChannelId()), uint(stackServer.getNextTokenId()), DateTime.now(), uint(channelLifetime));
SecurityKeys newKeys = null;
if (secureChannel.isSymmetricSigningEnabled()) {
// Validate the remote nonce; it must be non-null and the correct length for the security algorithm.
ByteString remoteNonce = request.getClientNonce();
NonceUtil.validateNonce(remoteNonce, secureChannel.getSecurityPolicy());
ByteString localNonce = generateNonce(secureChannel.getSecurityPolicy());
secureChannel.setLocalNonce(localNonce);
secureChannel.setRemoteNonce(remoteNonce);
newKeys = ChannelSecurity.generateKeyPair(secureChannel, secureChannel.getRemoteNonce(), secureChannel.getLocalNonce());
}
ChannelSecurity oldSecrets = secureChannel.getChannelSecurity();
SecurityKeys oldKeys = oldSecrets != null ? oldSecrets.getCurrentKeys() : null;
ChannelSecurityToken oldToken = oldSecrets != null ? oldSecrets.getCurrentToken() : null;
ChannelSecurity newSecrets = new ChannelSecurity(newKeys, newToken, oldKeys, oldToken);
secureChannel.setChannelSecurity(newSecrets);
/*
* Cancel the previous timeout, if it exists, and start a new one.
*/
if (secureChannelTimeout == null || secureChannelTimeout.cancel()) {
final long lifetime = channelLifetime;
secureChannelTimeout = Stack.sharedWheelTimer().newTimeout(timeout -> {
logger.debug("SecureChannel renewal timed out after {}ms. id={}, channel={}", lifetime, secureChannel.getChannelId(), ctx.channel());
ctx.close();
}, channelLifetime, TimeUnit.MILLISECONDS);
}
ResponseHeader responseHeader = new ResponseHeader(DateTime.now(), request.getRequestHeader().getRequestHandle(), StatusCode.GOOD, null, null, null);
return new OpenSecureChannelResponse(responseHeader, uint(PROTOCOL_VERSION), newToken, secureChannel.getLocalNonce());
}
Aggregations