use of org.eclipse.milo.opcua.stack.core.channel.ServerSecureChannel in project milo by eclipse.
the class UascServerAsymmetricHandler method onOpenSecureChannel.
private void onOpenSecureChannel(ChannelHandlerContext ctx, ByteBuf buffer) throws UaException {
// Skip messageType
buffer.skipBytes(3);
char chunkType = (char) buffer.readByte();
if (chunkType == 'A') {
chunkBuffers.forEach(ByteBuf::release);
chunkBuffers.clear();
headerRef.set(null);
} else {
// Skip messageSize
buffer.skipBytes(4);
final long secureChannelId = buffer.readUnsignedIntLE();
final AsymmetricSecurityHeader header = AsymmetricSecurityHeader.decode(buffer, stackServer.getConfig().getEncodingLimits());
if (!headerRef.compareAndSet(null, header)) {
if (!header.equals(headerRef.get())) {
throw new UaException(StatusCodes.Bad_SecurityChecksFailed, "subsequent AsymmetricSecurityHeader did not match");
}
}
if (secureChannelId != 0) {
if (secureChannel == null) {
throw new UaException(StatusCodes.Bad_TcpSecureChannelUnknown, "unknown secure channel id: " + secureChannelId);
}
if (secureChannelId != secureChannel.getChannelId()) {
throw new UaException(StatusCodes.Bad_TcpSecureChannelUnknown, "unknown secure channel id: " + secureChannelId);
}
}
if (secureChannel == null) {
secureChannel = new ServerSecureChannel();
secureChannel.setChannelId(stackServer.getNextChannelId());
String securityPolicyUri = header.getSecurityPolicyUri();
SecurityPolicy securityPolicy = SecurityPolicy.fromUri(securityPolicyUri);
secureChannel.setSecurityPolicy(securityPolicy);
if (securityPolicy != SecurityPolicy.None) {
secureChannel.setRemoteCertificate(header.getSenderCertificate().bytesOrEmpty());
CertificateValidator certificateValidator = stackServer.getConfig().getCertificateValidator();
certificateValidator.validateCertificateChain(secureChannel.getRemoteCertificateChain());
CertificateManager certificateManager = stackServer.getConfig().getCertificateManager();
Optional<X509Certificate[]> localCertificateChain = certificateManager.getCertificateChain(header.getReceiverThumbprint());
Optional<KeyPair> keyPair = certificateManager.getKeyPair(header.getReceiverThumbprint());
if (localCertificateChain.isPresent() && keyPair.isPresent()) {
X509Certificate[] chain = localCertificateChain.get();
secureChannel.setLocalCertificate(chain[0]);
secureChannel.setLocalCertificateChain(chain);
secureChannel.setKeyPair(keyPair.get());
} else {
throw new UaException(StatusCodes.Bad_SecurityChecksFailed, "no certificate for provided thumbprint");
}
}
}
int chunkSize = buffer.readerIndex(0).readableBytes();
if (chunkSize > maxChunkSize) {
throw new UaException(StatusCodes.Bad_TcpMessageTooLarge, String.format("max chunk size exceeded (%s)", maxChunkSize));
}
chunkBuffers.add(buffer.retain());
if (maxChunkCount > 0 && chunkBuffers.size() > maxChunkCount) {
throw new UaException(StatusCodes.Bad_TcpMessageTooLarge, String.format("max chunk count exceeded (%s)", maxChunkCount));
}
if (chunkType == 'F') {
final List<ByteBuf> buffersToDecode = chunkBuffers;
chunkBuffers = new ArrayList<>();
headerRef.set(null);
serializationQueue.decode((binaryDecoder, chunkDecoder) -> {
ByteBuf message;
long requestId;
try {
ChunkDecoder.DecodedMessage decodedMessage = chunkDecoder.decodeAsymmetric(secureChannel, buffersToDecode);
message = decodedMessage.getMessage();
requestId = decodedMessage.getRequestId();
} catch (MessageAbortException e) {
logger.warn("Received message abort chunk; error={}, reason={}", e.getStatusCode(), e.getMessage());
return;
} catch (MessageDecodeException e) {
logger.error("Error decoding asymmetric message", e);
ctx.close();
return;
}
try {
OpenSecureChannelRequest request = (OpenSecureChannelRequest) binaryDecoder.setBuffer(message).readMessage(null);
logger.debug("Received OpenSecureChannelRequest ({}, id={}).", request.getRequestType(), secureChannelId);
sendOpenSecureChannelResponse(ctx, requestId, request);
} catch (Throwable t) {
logger.error("Error decoding OpenSecureChannelRequest", t);
ctx.close();
} finally {
message.release();
buffersToDecode.clear();
}
});
}
}
}
use of org.eclipse.milo.opcua.stack.core.channel.ServerSecureChannel in project milo by eclipse.
the class ChunkSerializationTest method testSymmetric4096.
@Test
public void testSymmetric4096() throws Exception {
ChannelParameters parameters = defaultParameters;
ChunkEncoder encoder = new ChunkEncoder(parameters);
ChunkDecoder decoder = new ChunkDecoder(parameters, EncodingLimits.DEFAULT);
SecureChannel[] channels = generateChannels4096();
ClientSecureChannel clientChannel = (ClientSecureChannel) channels[0];
ServerSecureChannel serverChannel = (ServerSecureChannel) channels[1];
clientChannel.attr(ClientSecureChannel.KEY_REQUEST_ID_SEQUENCE).setIfAbsent(new LongSequence(1L, UInteger.MAX_VALUE));
LongSequence requestId = clientChannel.attr(ClientSecureChannel.KEY_REQUEST_ID_SEQUENCE).get();
for (int messageSize = 0; messageSize < 1024; messageSize++) {
byte[] messageBytes = new byte[messageSize];
for (int i = 0; i < messageBytes.length; i++) {
messageBytes[i] = (byte) i;
}
ByteBuf messageBuffer = BufferUtil.pooledBuffer().writeBytes(messageBytes);
List<ByteBuf> chunkBuffers = new ArrayList<>();
try {
ChunkEncoder.EncodedMessage message = encoder.encodeSymmetric(clientChannel, requestId.getAndIncrement(), messageBuffer, MessageType.OpenSecureChannel);
chunkBuffers.addAll(message.getMessageChunks());
} catch (MessageEncodeException e) {
fail("encoding error", e);
}
try {
ChunkDecoder.DecodedMessage decodedMessage = decoder.decodeSymmetric(serverChannel, chunkBuffers);
ByteBuf message = decodedMessage.getMessage();
messageBuffer.readerIndex(0);
assertEquals(message, messageBuffer);
ReferenceCountUtil.release(message);
ReferenceCountUtil.release(messageBuffer);
} catch (Throwable t) {
fail("decoding error", t);
}
}
}
use of org.eclipse.milo.opcua.stack.core.channel.ServerSecureChannel in project milo by eclipse.
the class ChunkSerializationTest method testAsymmetric4096.
@Test
public void testAsymmetric4096() throws Exception {
ChannelParameters parameters = defaultParameters;
ChunkEncoder encoder = new ChunkEncoder(parameters);
ChunkDecoder decoder = new ChunkDecoder(parameters, EncodingLimits.DEFAULT);
SecureChannel[] channels = generateChannels4096();
ClientSecureChannel clientChannel = (ClientSecureChannel) channels[0];
ServerSecureChannel serverChannel = (ServerSecureChannel) channels[1];
clientChannel.attr(ClientSecureChannel.KEY_REQUEST_ID_SEQUENCE).setIfAbsent(new LongSequence(1L, UInteger.MAX_VALUE));
LongSequence requestId = clientChannel.attr(ClientSecureChannel.KEY_REQUEST_ID_SEQUENCE).get();
for (int messageSize = 0; messageSize < 512; messageSize++) {
byte[] messageBytes = new byte[messageSize];
for (int i = 0; i < messageBytes.length; i++) {
messageBytes[i] = (byte) i;
}
ByteBuf messageBuffer = BufferUtil.pooledBuffer().writeBytes(messageBytes);
List<ByteBuf> chunkBuffers = new ArrayList<>();
try {
ChunkEncoder.EncodedMessage message = encoder.encodeAsymmetric(clientChannel, requestId.getAndIncrement(), messageBuffer, MessageType.OpenSecureChannel);
chunkBuffers.addAll(message.getMessageChunks());
} catch (MessageEncodeException e) {
fail("encoding error", e);
}
try {
ChunkDecoder.DecodedMessage decodedMessage = decoder.decodeAsymmetric(serverChannel, chunkBuffers);
ByteBuf message = decodedMessage.getMessage();
messageBuffer.readerIndex(0);
assertEquals(message, messageBuffer);
ReferenceCountUtil.release(message);
ReferenceCountUtil.release(messageBuffer);
} catch (Throwable t) {
fail("decoding error", t);
}
}
}
use of org.eclipse.milo.opcua.stack.core.channel.ServerSecureChannel in project milo by eclipse.
the class ChunkSerializationTest method testSymmetricMessage.
@Test(dataProvider = "getSymmetricSecurityParameters")
public void testSymmetricMessage(SecurityPolicy securityPolicy, MessageSecurityMode messageSecurity) throws Exception {
logger.info("Symmetric chunk serialization, " + "securityPolicy={}, messageSecurityMode={}", securityPolicy, messageSecurity);
ChannelParameters[] channelParameters = { smallParameters, defaultParameters, unlimitedChunkCountParameters, unlimitedMessageSizeParameters };
for (ChannelParameters parameters : channelParameters) {
int[] messageSizes = new int[] { 128, parameters.getRemoteMaxMessageSize() };
for (int messageSize : messageSizes) {
ChunkEncoder encoder = new ChunkEncoder(parameters);
ChunkDecoder decoder = new ChunkDecoder(parameters, EncodingLimits.DEFAULT);
SecureChannel[] channels = generateChannels(securityPolicy, messageSecurity);
ClientSecureChannel clientChannel = (ClientSecureChannel) channels[0];
ServerSecureChannel serverChannel = (ServerSecureChannel) channels[1];
clientChannel.attr(ClientSecureChannel.KEY_REQUEST_ID_SEQUENCE).setIfAbsent(new LongSequence(1L, UInteger.MAX_VALUE));
LongSequence requestId = clientChannel.attr(ClientSecureChannel.KEY_REQUEST_ID_SEQUENCE).get();
byte[] messageBytes = new byte[messageSize];
for (int i = 0; i < messageBytes.length; i++) {
messageBytes[i] = (byte) i;
}
ByteBuf messageBuffer = BufferUtil.pooledBuffer().writeBytes(messageBytes);
List<ByteBuf> chunkBuffers = new ArrayList<>();
try {
ChunkEncoder.EncodedMessage message = encoder.encodeSymmetric(clientChannel, requestId.getAndIncrement(), messageBuffer, MessageType.SecureMessage);
chunkBuffers.addAll(message.getMessageChunks());
} catch (MessageEncodeException e) {
fail("encoding error", e);
}
try {
ChunkDecoder.DecodedMessage decodedMessage = decoder.decodeSymmetric(serverChannel, chunkBuffers);
ByteBuf message = decodedMessage.getMessage();
messageBuffer.readerIndex(0);
assertEquals(message, messageBuffer);
ReferenceCountUtil.release(messageBuffer);
ReferenceCountUtil.release(message);
} catch (Throwable t) {
fail("decoding error", t);
}
}
}
}
use of org.eclipse.milo.opcua.stack.core.channel.ServerSecureChannel 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 };
}
Aggregations