From 0e9cd8cf4543a37dcc0ded2cf81f8199e26c4838 Mon Sep 17 00:00:00 2001
From: lys1737 <296343318@qq.com>
Date: Tue, 6 Sep 2022 11:30:06 +0800
Subject: [PATCH] In order to use other lib to handler password like JWT etc.
 And get networkModule real info to generate signature. Signed-off-by: lys1737
 <296343318@qq.com>

---
 .../client-1-tcplocalhost1883/.lck            |   0
 .../client/mqttv3/test/DynamicPwdTest.java    | 123 ++++++++++++++++++
 .../client/mqttv3/internal/ClientComms.java   |  32 +++--
 .../paho/client/mqttv3/PasswdHandler.java     |  38 ++++++
 .../mqttv3/internal/wire/MqttConnect.java     |   8 ++
 5 files changed, 184 insertions(+), 17 deletions(-)
 create mode 100644 org.eclipse.paho.client.mqttv3.test/client-1-tcplocalhost1883/.lck
 create mode 100644 org.eclipse.paho.client.mqttv3.test/src/test/java/org/eclipse/paho/client/mqttv3/test/DynamicPwdTest.java
 create mode 100644 org.eclipse.paho.client.mqttv3/src/main/java/org/eclipse/paho/client/mqttv3/PasswdHandler.java

diff --git a/org.eclipse.paho.client.mqttv3.test/client-1-tcplocalhost1883/.lck b/org.eclipse.paho.client.mqttv3.test/client-1-tcplocalhost1883/.lck
new file mode 100644
index 000000000..e69de29bb
diff --git a/org.eclipse.paho.client.mqttv3.test/src/test/java/org/eclipse/paho/client/mqttv3/test/DynamicPwdTest.java b/org.eclipse.paho.client.mqttv3.test/src/test/java/org/eclipse/paho/client/mqttv3/test/DynamicPwdTest.java
new file mode 100644
index 000000000..7668caf2e
--- /dev/null
+++ b/org.eclipse.paho.client.mqttv3.test/src/test/java/org/eclipse/paho/client/mqttv3/test/DynamicPwdTest.java
@@ -0,0 +1,123 @@
+/* Copyright (c) 2009, 2014 IBM Corp.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v2.0
+ * and Eclipse Distribution License v1.0 which accompany this distribution. 
+ *
+ * The Eclipse Public License is available at 
+ *    https://www.eclipse.org/legal/epl-2.0
+ * and the Eclipse Distribution License is available at 
+ *   https://www.eclipse.org/org/documents/edl-v10.php
+ *
+ *******************************************************************************/
+
+package org.eclipse.paho.client.mqttv3.test;
+
+import org.eclipse.paho.client.mqttv3.*;
+import org.eclipse.paho.client.mqttv3.internal.NetworkModule;
+import org.eclipse.paho.client.mqttv3.test.client.MqttClientFactoryPaho;
+import org.eclipse.paho.client.mqttv3.test.logging.LoggingUtilities;
+import org.eclipse.paho.client.mqttv3.test.properties.TestProperties;
+import org.eclipse.paho.client.mqttv3.test.utilities.Utility;
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import java.net.URI;
+import java.util.UUID;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+
+/**
+ * Tests providing how to use PasswdHandler to change password when client connecct.
+ */
+public class DynamicPwdTest {
+
+  static final Class<?> cclass = DynamicPwdTest.class;
+  private static final String className = cclass.getName();
+  private static final Logger log = Logger.getLogger(className);
+
+  private static URI serverURI;
+  private static MqttClientFactoryPaho clientFactory;
+  private static String topicPrefix;
+
+
+  /**
+   * @throws Exception 
+   */
+  @BeforeClass
+  public static void setUpBeforeClass() throws Exception {
+
+    try {
+      String methodName = Utility.getMethodName();
+      LoggingUtilities.banner(log, cclass, methodName);
+
+      serverURI = TestProperties.getServerURI();
+      clientFactory = new MqttClientFactoryPaho();
+      clientFactory.open();
+      topicPrefix = "BasicTest-" + UUID.randomUUID().toString() + "-";
+
+    }
+    catch (Exception exception) {
+      log.log(Level.SEVERE, "caught exception:", exception);
+      throw exception;
+    }
+  }
+
+  /**
+   * @throws Exception
+   */
+  @AfterClass
+  public static void tearDownAfterClass() throws Exception {
+    String methodName = Utility.getMethodName();
+    LoggingUtilities.banner(log, cclass, methodName);
+
+    try {
+      if (clientFactory != null) {
+        clientFactory.close();
+        clientFactory.disconnect();
+      }
+    }
+    catch (Exception exception) {
+      log.log(Level.SEVERE, "caught exception:", exception);
+    }
+  }
+
+
+  @Test
+  public void testDynamicPwd() throws Exception {
+    String methodName = Utility.getMethodName();
+    LoggingUtilities.banner(log, cclass, methodName);
+
+    PasswdHandler.Factory.setPasswdHandler(new TestPasswdHandler());
+
+    IMqttAsyncClient client = clientFactory.createMqttAsyncClient(serverURI, "client-1");
+
+    MqttConnectOptions options = new MqttConnectOptions();
+    options.setAutomaticReconnect(true);
+    options.setUserName("foo");
+    options.setPassword("123456".toCharArray());
+    options.setConnectionTimeout(2);
+    client.connect(options);
+
+    Thread.sleep(1000);
+
+    try {
+      client.disconnect(0).waitForCompletion();
+    } finally {
+      client.close();
+    }
+
+  }
+
+  public class TestPasswdHandler implements PasswdHandler {
+
+    @Override
+    public String handler(NetworkModule networkModule) {
+      String url = networkModule.getServerURI();
+      String msg = "url:"+url + ",timestamp:" + System.currentTimeMillis();
+      log.info(msg);
+      return msg;
+    }
+  }
+}
diff --git a/org.eclipse.paho.client.mqttv3/src/main/java-templates/org/eclipse/paho/client/mqttv3/internal/ClientComms.java b/org.eclipse.paho.client.mqttv3/src/main/java-templates/org/eclipse/paho/client/mqttv3/internal/ClientComms.java
index b0c433498..0f5fbbe63 100644
--- a/org.eclipse.paho.client.mqttv3/src/main/java-templates/org/eclipse/paho/client/mqttv3/internal/ClientComms.java
+++ b/org.eclipse.paho.client.mqttv3/src/main/java-templates/org/eclipse/paho/client/mqttv3/internal/ClientComms.java
@@ -25,22 +25,7 @@
 import java.util.concurrent.ExecutorService;
 import java.util.concurrent.TimeUnit;
 
-import org.eclipse.paho.client.mqttv3.BufferedMessage;
-import org.eclipse.paho.client.mqttv3.IMqttActionListener;
-import org.eclipse.paho.client.mqttv3.IMqttAsyncClient;
-import org.eclipse.paho.client.mqttv3.IMqttMessageListener;
-import org.eclipse.paho.client.mqttv3.IMqttDeliveryToken;
-import org.eclipse.paho.client.mqttv3.MqttCallback;
-import org.eclipse.paho.client.mqttv3.MqttCallbackExtended;
-import org.eclipse.paho.client.mqttv3.MqttClientPersistence;
-import org.eclipse.paho.client.mqttv3.MqttConnectOptions;
-import org.eclipse.paho.client.mqttv3.MqttDeliveryToken;
-import org.eclipse.paho.client.mqttv3.MqttException;
-import org.eclipse.paho.client.mqttv3.MqttMessage;
-import org.eclipse.paho.client.mqttv3.MqttPersistenceException;
-import org.eclipse.paho.client.mqttv3.MqttPingSender;
-import org.eclipse.paho.client.mqttv3.MqttToken;
-import org.eclipse.paho.client.mqttv3.MqttTopic;
+import org.eclipse.paho.client.mqttv3.*;
 import org.eclipse.paho.client.mqttv3.internal.wire.MqttConnack;
 import org.eclipse.paho.client.mqttv3.internal.wire.MqttConnect;
 import org.eclipse.paho.client.mqttv3.internal.wire.MqttDisconnect;
@@ -717,13 +702,26 @@ public void run() {
 				}
 
 				// Save the connect token in tokenStore as failure can occur before send
-				tokenStore.saveToken(conToken,conPacket);
+				//tokenStore.saveToken(conToken,conPacket);
 
 				// Connect to the server at the network level e.g. TCP socket and then
 				// start the background processing threads before sending the connect
 				// packet.
 				NetworkModule networkModule = networkModules[networkModuleIndex];
 				networkModule.start();
+
+				//use passHandler to change password before connect, and get networkModule real info to generate signature like JWT etc.
+				PasswdHandler passwdHandler = PasswdHandler.Factory.getInstance();
+				if(null != passwdHandler){
+					String pwd = PasswdHandler.Factory.getInstance().handler(networkModule);
+					if(null != pwd && !"".equals(pwd)){
+						conPacket.setPassword(pwd.toCharArray());
+					}
+					tokenStore.saveToken(conToken,conPacket);
+				}else{
+					tokenStore.saveToken(conToken,conPacket);
+				}
+
 				receiver = new CommsReceiver(clientComms, clientState, tokenStore, networkModule.getInputStream());
 				receiver.start("MQTT Rec: "+getClient().getClientId(), executorService);
 				sender = new CommsSender(clientComms, clientState, tokenStore, networkModule.getOutputStream());
diff --git a/org.eclipse.paho.client.mqttv3/src/main/java/org/eclipse/paho/client/mqttv3/PasswdHandler.java b/org.eclipse.paho.client.mqttv3/src/main/java/org/eclipse/paho/client/mqttv3/PasswdHandler.java
new file mode 100644
index 000000000..f7301f532
--- /dev/null
+++ b/org.eclipse.paho.client.mqttv3/src/main/java/org/eclipse/paho/client/mqttv3/PasswdHandler.java
@@ -0,0 +1,38 @@
+/*******************************************************************************
+ * Copyright (c) 2014 IBM Corp.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v2.0
+ * and Eclipse Distribution License v1.0 which accompany this distribution.
+ *
+ * The Eclipse Public License is available at
+ *    https://www.eclipse.org/legal/epl-2.0
+ * and the Eclipse Distribution License is available at
+ *   https://www.eclipse.org/org/documents/edl-v10.php
+ *
+ */
+package org.eclipse.paho.client.mqttv3;
+
+
+import org.eclipse.paho.client.mqttv3.internal.NetworkModule;
+
+/**
+ *  In order to use other lib to handler password like JWT etc.
+ *  Get networkModule real info to generate signature.
+ */
+public interface PasswdHandler {
+
+    String handler(NetworkModule networkModule);
+
+    class Factory{
+        public static PasswdHandler passwdHandler;
+
+        public static void setPasswdHandler(PasswdHandler passwdHandler){
+            Factory.passwdHandler = passwdHandler;
+        }
+
+        public static PasswdHandler getInstance(){
+            return passwdHandler;
+        }
+    }
+}
diff --git a/org.eclipse.paho.client.mqttv3/src/main/java/org/eclipse/paho/client/mqttv3/internal/wire/MqttConnect.java b/org.eclipse.paho.client.mqttv3/src/main/java/org/eclipse/paho/client/mqttv3/internal/wire/MqttConnect.java
index 791250176..790222f3e 100644
--- a/org.eclipse.paho.client.mqttv3/src/main/java/org/eclipse/paho/client/mqttv3/internal/wire/MqttConnect.java
+++ b/org.eclipse.paho.client.mqttv3/src/main/java/org/eclipse/paho/client/mqttv3/internal/wire/MqttConnect.java
@@ -41,6 +41,14 @@ public class MqttConnect extends MqttWireMessage {
 	private String willDestination;
 	private int mqttVersion;
 
+	/**
+	 * allow to change password after new MqttConnect, use dynamic password to connect server.
+	 * @param password
+	 */
+	public void setPassword(char[] password){
+		this.password = password;
+	}
+
 	/**
 	 * Constructor for an on the wire MQTT connect message
 	 *