From 6319e18df75cc0a11914aac73bf15d4f9e59b3c4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Dywicki?= Date: Wed, 3 Apr 2024 00:00:20 +0200 Subject: [PATCH] Attempt to fix token refreshing logic. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Ɓukasz Dywicki --- .../java/opcua/context/Conversation.java | 17 +++++++--- .../java/opcua/context/SecureChannel.java | 34 +++++++++++++------ 2 files changed, 36 insertions(+), 15 deletions(-) diff --git a/plc4j/drivers/opcua/src/main/java/org/apache/plc4x/java/opcua/context/Conversation.java b/plc4j/drivers/opcua/src/main/java/org/apache/plc4x/java/opcua/context/Conversation.java index d398d76951e..c5203d33745 100644 --- a/plc4j/drivers/opcua/src/main/java/org/apache/plc4x/java/opcua/context/Conversation.java +++ b/plc4j/drivers/opcua/src/main/java/org/apache/plc4x/java/opcua/context/Conversation.java @@ -147,7 +147,7 @@ public Conversation(ConversationContext context, OpcuaDriverContext dr this.remoteCertificate = configuration.getServerCertificate(); this.encryptionHandler = new EncryptionHandler(this, senderKeyPair.getPrivateKey()); this.localCertificate = senderKeyPair.getCertificate(); - this.localNonce = createNonce(); + //this.localNonce = createNonce(); } else { this.messageSecurity = MessageSecurity.NONE; this.encryptionHandler = new EncryptionHandler(this, null); @@ -383,8 +383,12 @@ private boolean accumulateChunkUntilFinal(ChunkStorage storage, ChunkType chunkT return FINAL.equals(chunkType); } + public byte[] getLocalNonce() { + return localNonce; + } + // generate nonce used for setting up signing/encryption keys - private byte[] createNonce() { + public byte[] createNonce() { return createNonce(securityPolicy.getNonceLength()); } @@ -423,8 +427,8 @@ public OpcuaProtocolLimits getLimits() { return limits; } - public byte[] getLocalNonce() { - return localNonce; + public void setLocalNonce(byte[] nonce) { + this.localNonce = nonce; } public X509Certificate getLocalCertificate() { @@ -459,6 +463,10 @@ public void setSecurityHeader(SecurityHeader securityHeader) { this.securityHeader.set(securityHeader); } + public SecurityHeader getSecurityHeader() { + return securityHeader.get(); + } + public SignatureData createClientSignature() throws GeneralSecurityException { return encryptionHandler.createClientSignature(); } @@ -494,4 +502,5 @@ public static long getCurrentDateTime() { public void setAuthenticationToken(NodeIdTypeDefinition authenticationToken) { this.authenticationToken.set(authenticationToken); } + } diff --git a/plc4j/drivers/opcua/src/main/java/org/apache/plc4x/java/opcua/context/SecureChannel.java b/plc4j/drivers/opcua/src/main/java/org/apache/plc4x/java/opcua/context/SecureChannel.java index 8c8b4ad56ba..48f8c34a081 100644 --- a/plc4j/drivers/opcua/src/main/java/org/apache/plc4x/java/opcua/context/SecureChannel.java +++ b/plc4j/drivers/opcua/src/main/java/org/apache/plc4x/java/opcua/context/SecureChannel.java @@ -160,13 +160,14 @@ public CompletableFuture onConnect() { } public CompletableFuture onConnectOpenSecureChannel(SecurityTokenRequestType securityTokenRequestType) { - LOGGER.debug("Sending open secure channel message to {}", this.driverContext.getEndpoint()); + LOGGER.debug("Sending open secure channel request {} message to {}", securityTokenRequestType, this.driverContext.getEndpoint()); RequestHeader requestHeader = conversation.createRequestHeader(configuration.getNegotiationTimeout(), 0); + byte[] localNonce = new byte[0]; OpenSecureChannelRequest openSecureChannelRequest; if (conversation.getSecurityPolicy() != SecurityPolicy.NONE) { - byte[] localNonce = conversation.getLocalNonce(); + localNonce = conversation.createNonce(); openSecureChannelRequest = new OpenSecureChannelRequest( requestHeader, OpcuaConstants.PROTOCOLVERSION, @@ -185,6 +186,7 @@ public CompletableFuture onConnectOpenSecureChannel(S configuration.getChannelLifetime() // lifetime ); } + conversation.setLocalNonce(localNonce); ExpandedNodeId expandedNodeId = new ExpandedNodeId(false, false, new NodeIdFourByte((short) 0, Integer.parseInt(openSecureChannelRequest.getIdentifier())), @@ -213,17 +215,20 @@ public CompletableFuture onConnectOpenSecureChannel(S }) .thenApply(this::onOpenResponse) .thenApply(openSecureChannelResponse -> { - ChannelSecurityToken securityToken = (ChannelSecurityToken) openSecureChannelResponse.getSecurityToken(); + ChannelSecurityToken receivedToken = (ChannelSecurityToken) openSecureChannelResponse.getSecurityToken(); LOGGER.debug("Opened secure response id: {}, channel id:{}, token:{} lifetime:{}", openSecureChannelResponse.getIdentifier(), - securityToken.getChannelId(), securityToken.getTokenId(), securityToken.getRevisedLifetime()); - - conversation.setSecurityHeader(new SecurityHeader(securityToken.getChannelId(), securityToken.getTokenId())); - revisedLifetime = securityToken.getRevisedLifetime(); + receivedToken.getChannelId(), receivedToken.getTokenId(), receivedToken.getRevisedLifetime()); + conversation.setSecurityHeader(new SecurityHeader(receivedToken.getChannelId(), receivedToken.getTokenId())); + revisedLifetime = 5_000; //securityToken.getRevisedLifetime(); return openSecureChannelResponse; }); } public CompletableFuture onConnectCreateSessionRequest(OpenSecureChannelResponse response) { + return onConnectCreateSessionRequest(response.getServerNonce().getStringValue(), (ChannelSecurityToken) response.getSecurityToken()); + } + + public CompletableFuture onConnectCreateSessionRequest(byte[] serverNonce, ChannelSecurityToken securityToken) { LOGGER.debug("Sending create session request to {}", this.driverContext.getEndpoint()); RequestHeader requestHeader = conversation.createRequestHeader(); @@ -248,11 +253,10 @@ public CompletableFuture onConnectCreateSessionRequest(Op discoveryUrls ); - ChannelSecurityToken securityToken = (ChannelSecurityToken) response.getSecurityToken(); - LOGGER.debug("Opened secure response id: {}, channel id:{}, token:{} lifetime:{}", response.getIdentifier(), - securityToken.getChannelId(), securityToken.getTokenId(), securityToken.getRevisedLifetime()); + LOGGER.debug("Opened secure response channel id:{}, token:{} lifetime:{}", securityToken.getChannelId(), + securityToken.getTokenId(), securityToken.getRevisedLifetime()); - conversation.setRemoteNonce(response.getServerNonce().getStringValue()); + conversation.setRemoteNonce(serverNonce); byte[] temporaryNonce = conversation.createNonce(32); CreateSessionRequest createSessionRequest = new CreateSessionRequest( requestHeader, @@ -476,7 +480,15 @@ private void keepAlive() { keepAlive = KEEP_ALIVE_EXECUTOR.schedule(() -> { RequestTransaction transaction = tm.startRequest(); transaction.submit(() -> { +// SecurityHeader header = conversation.getSecurityHeader(); onConnectOpenSecureChannel(SecurityTokenRequestType.securityTokenRequestTypeRenew) +// onConnectCreateSessionRequest(conversation.getRemoteNonce(), +// new ChannelSecurityToken( +// header.getSecureChannelId(), +// header.getSecureTokenId(), +// 0, +// revisedLifetime +// )) .whenComplete((response, error) -> { if (error != null) { transaction.failRequest(error);