use of org.eclipse.milo.opcua.stack.core.channel.ChannelSecurity 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());
}
use of org.eclipse.milo.opcua.stack.core.channel.ChannelSecurity in project milo by eclipse.
the class SecureChannelFixture method generateChannels.
protected SecureChannel[] generateChannels(SecurityPolicy securityPolicy, MessageSecurityMode messageSecurity) throws Exception {
super.setUp();
ByteString clientNonce = generateNonce(securityPolicy);
ByteString serverNonce = generateNonce(securityPolicy);
ClientSecureChannel clientChannel = new ClientSecureChannel(securityPolicy == SecurityPolicy.None ? null : clientKeyPair, securityPolicy == SecurityPolicy.None ? null : clientCertificate, securityPolicy == SecurityPolicy.None ? null : newArrayList(clientCertificate), securityPolicy == SecurityPolicy.None ? null : serverCertificate, securityPolicy == SecurityPolicy.None ? null : newArrayList(serverCertificate), securityPolicy, messageSecurity);
clientChannel.setLocalNonce(clientNonce);
clientChannel.setRemoteNonce(serverNonce);
ServerSecureChannel serverChannel = new ServerSecureChannel();
serverChannel.setSecurityPolicy(securityPolicy);
serverChannel.setMessageSecurityMode(messageSecurity);
serverChannel.setLocalNonce(serverNonce);
serverChannel.setRemoteNonce(clientNonce);
if (securityPolicy != SecurityPolicy.None) {
serverChannel.setKeyPair(serverKeyPair);
serverChannel.setLocalCertificate(serverCertificate);
serverChannel.setLocalCertificateChain(new X509Certificate[] { serverCertificate });
serverChannel.setRemoteCertificate(clientCertificateBytes);
}
// Configure the ChannelSecurityToken for clientChannel
ChannelSecurityToken clientToken = new ChannelSecurityToken(uint(0), uint(1), DateTime.now(), uint(60000));
if (messageSecurity == MessageSecurityMode.None) {
clientChannel.setChannelSecurity(new ChannelSecurity(null, clientToken));
} else {
ChannelSecurity.SecurityKeys clientSecrets = ChannelSecurity.generateKeyPair(clientChannel, clientChannel.getLocalNonce(), clientChannel.getRemoteNonce());
clientChannel.setChannelSecurity(new ChannelSecurity(clientSecrets, clientToken));
}
// Configure the ChannelSecurityToken for serverChannel
ChannelSecurityToken serverToken = new ChannelSecurityToken(uint(0), uint(1), DateTime.now(), uint(60000));
if (messageSecurity == MessageSecurityMode.None) {
serverChannel.setChannelSecurity(new ChannelSecurity(null, serverToken));
} else {
ChannelSecurity.SecurityKeys serverSecrets = ChannelSecurity.generateKeyPair(serverChannel, serverChannel.getRemoteNonce(), serverChannel.getLocalNonce());
serverChannel.setChannelSecurity(new ChannelSecurity(serverSecrets, serverToken));
}
return new SecureChannel[] { clientChannel, serverChannel };
}
use of org.eclipse.milo.opcua.stack.core.channel.ChannelSecurity in project milo by eclipse.
the class UascClientMessageHandler method installSecurityToken.
private void installSecurityToken(ChannelHandlerContext ctx, OpenSecureChannelResponse response) {
ChannelSecurity.SecurityKeys newKeys = null;
if (response.getServerProtocolVersion().longValue() < PROTOCOL_VERSION) {
throw new UaRuntimeException(StatusCodes.Bad_ProtocolVersionUnsupported, "server protocol version unsupported: " + response.getServerProtocolVersion());
}
ChannelSecurityToken newToken = response.getSecurityToken();
if (secureChannel.isSymmetricSigningEnabled()) {
secureChannel.setRemoteNonce(response.getServerNonce());
newKeys = ChannelSecurity.generateKeyPair(secureChannel, secureChannel.getLocalNonce(), secureChannel.getRemoteNonce());
}
ChannelSecurity oldSecrets = secureChannel.getChannelSecurity();
ChannelSecurity.SecurityKeys oldKeys = oldSecrets != null ? oldSecrets.getCurrentKeys() : null;
ChannelSecurityToken oldToken = oldSecrets != null ? oldSecrets.getCurrentToken() : null;
secureChannel.setChannelSecurity(new ChannelSecurity(newKeys, newToken, oldKeys, oldToken));
DateTime createdAt = response.getSecurityToken().getCreatedAt();
long revisedLifetime = response.getSecurityToken().getRevisedLifetime().longValue();
if (revisedLifetime > 0) {
long renewAt = (long) (revisedLifetime * 0.75);
renewFuture = ctx.executor().schedule(() -> sendOpenSecureChannelRequest(ctx, SecurityTokenRequestType.Renew), renewAt, TimeUnit.MILLISECONDS);
} else {
logger.warn("Server revised secure channel lifetime to 0; renewal will not occur.");
}
ctx.executor().execute(() -> {
// SecureChannel is ready; remove the acknowledge handler.
if (ctx.pipeline().get(UascClientAcknowledgeHandler.class) != null) {
ctx.pipeline().remove(UascClientAcknowledgeHandler.class);
}
});
ChannelSecurity channelSecurity = secureChannel.getChannelSecurity();
long currentTokenId = channelSecurity.getCurrentToken().getTokenId().longValue();
long previousTokenId = channelSecurity.getPreviousToken().map(t -> t.getTokenId().longValue()).orElse(-1L);
logger.debug("SecureChannel id={}, currentTokenId={}, previousTokenId={}, lifetime={}ms, createdAt={}", secureChannel.getChannelId(), currentTokenId, previousTokenId, revisedLifetime, createdAt);
}
use of org.eclipse.milo.opcua.stack.core.channel.ChannelSecurity in project milo by eclipse.
the class UascClientMessageHandler method sendOpenSecureChannelRequest.
private void sendOpenSecureChannelRequest(ChannelHandlerContext ctx, SecurityTokenRequestType requestType) {
ByteString clientNonce = secureChannel.isSymmetricSigningEnabled() ? NonceUtil.generateNonce(secureChannel.getSecurityPolicy()) : ByteString.NULL_VALUE;
secureChannel.setLocalNonce(clientNonce);
RequestHeader header = new RequestHeader(null, DateTime.now(), uint(0), uint(0), null, config.getRequestTimeout(), null);
OpenSecureChannelRequest request = new OpenSecureChannelRequest(header, uint(PROTOCOL_VERSION), requestType, secureChannel.getMessageSecurityMode(), secureChannel.getLocalNonce(), config.getChannelLifetime());
serializationQueue.encode((binaryEncoder, chunkEncoder) -> {
ByteBuf messageBuffer = BufferUtil.pooledBuffer();
try {
binaryEncoder.setBuffer(messageBuffer);
binaryEncoder.writeMessage(null, request);
checkMessageSize(messageBuffer);
EncodedMessage encodedMessage = chunkEncoder.encodeAsymmetric(secureChannel, requestIdSequence.getAndIncrement(), messageBuffer, MessageType.OpenSecureChannel);
CompositeByteBuf chunkComposite = BufferUtil.compositeBuffer();
for (ByteBuf chunk : encodedMessage.getMessageChunks()) {
chunkComposite.addComponent(chunk);
chunkComposite.writerIndex(chunkComposite.writerIndex() + chunk.readableBytes());
}
ctx.writeAndFlush(chunkComposite, ctx.voidPromise());
ChannelSecurity channelSecurity = secureChannel.getChannelSecurity();
long currentTokenId = -1L;
if (channelSecurity != null) {
currentTokenId = channelSecurity.getCurrentToken().getTokenId().longValue();
}
long previousTokenId = -1L;
if (channelSecurity != null) {
previousTokenId = channelSecurity.getPreviousToken().map(token -> token.getTokenId().longValue()).orElse(-1L);
}
logger.debug("Sent OpenSecureChannelRequest ({}, id={}, currentToken={}, previousToken={}).", request.getRequestType(), secureChannel.getChannelId(), currentTokenId, previousTokenId);
} catch (MessageEncodeException e) {
logger.error("Error encoding {}: {}", request, e.getMessage(), e);
ctx.close();
} finally {
messageBuffer.release();
}
});
}
use of org.eclipse.milo.opcua.stack.core.channel.ChannelSecurity in project milo by eclipse.
the class SecureChannelFixture method generateChannels4096.
protected SecureChannel[] generateChannels4096() throws Exception {
super.setUp();
SecurityPolicy securityPolicy = SecurityPolicy.Basic256Sha256;
MessageSecurityMode messageSecurity = MessageSecurityMode.SignAndEncrypt;
ByteString clientNonce = generateNonce(securityPolicy);
ByteString serverNonce = generateNonce(securityPolicy);
ClientSecureChannel clientChannel = new ClientSecureChannel(clientKeyPair4096, clientCertificate4096, newArrayList(clientCertificate4096), serverCertificate4096, newArrayList(serverCertificate4096), securityPolicy, messageSecurity);
clientChannel.setLocalNonce(clientNonce);
clientChannel.setRemoteNonce(serverNonce);
ServerSecureChannel serverChannel = new ServerSecureChannel();
serverChannel.setSecurityPolicy(securityPolicy);
serverChannel.setMessageSecurityMode(messageSecurity);
serverChannel.setLocalNonce(serverNonce);
serverChannel.setRemoteNonce(clientNonce);
serverChannel.setKeyPair(serverKeyPair4096);
serverChannel.setLocalCertificate(serverCertificate4096);
serverChannel.setLocalCertificateChain(new X509Certificate[] { serverCertificate4096 });
serverChannel.setRemoteCertificate(clientCertificateBytes4096);
// Configure the ChannelSecurityToken for clientChannel
ChannelSecurityToken clientToken = new ChannelSecurityToken(uint(0), uint(1), DateTime.now(), uint(60000));
ChannelSecurity.SecurityKeys clientSecrets = ChannelSecurity.generateKeyPair(clientChannel, clientChannel.getLocalNonce(), clientChannel.getRemoteNonce());
clientChannel.setChannelSecurity(new ChannelSecurity(clientSecrets, clientToken));
// Configure the ChannelSecurityToken for serverChannel
ChannelSecurityToken serverToken = new ChannelSecurityToken(uint(0), uint(1), DateTime.now(), uint(60000));
ChannelSecurity.SecurityKeys serverSecrets = ChannelSecurity.generateKeyPair(serverChannel, serverChannel.getRemoteNonce(), serverChannel.getLocalNonce());
serverChannel.setChannelSecurity(new ChannelSecurity(serverSecrets, serverToken));
return new SecureChannel[] { clientChannel, serverChannel };
}
Aggregations