This commit is contained in:
@@ -35,3 +35,4 @@ broker/runner
|
|||||||
# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
|
# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
|
||||||
hs_err_pid*
|
hs_err_pid*
|
||||||
broker/moquette_store.*
|
broker/moquette_store.*
|
||||||
|
embedding_moquette/target/
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ Version 0.8:
|
|||||||
Fixed bug #81, on stop of moquette broker it doesn't shutdown due to no shutdown of ringbuffer used on the back of ProtocolProcessor
|
Fixed bug #81, on stop of moquette broker it doesn't shutdown due to no shutdown of ringbuffer used on the back of ProtocolProcessor
|
||||||
Moved config to be not only filesystem based, but also classpath and memory (fix issue #73)
|
Moved config to be not only filesystem based, but also classpath and memory (fix issue #73)
|
||||||
Switched from commit pesistence on every change to time based to fix delay in handling many msgs/sec (fix issue #79)
|
Switched from commit pesistence on every change to time based to fix delay in handling many msgs/sec (fix issue #79)
|
||||||
|
Changed willMessage and password in CONNECT message from String to byte[] (fix issue #94 and #95)
|
||||||
|
|
||||||
Version 0.7:
|
Version 0.7:
|
||||||
Fix issue #38, added aligned to MQTT 3.1.1
|
Fix issue #38, added aligned to MQTT 3.1.1
|
||||||
|
|||||||
+2
-2
@@ -57,7 +57,7 @@ public class InterceptConnectMessage extends InterceptAbstractMessage {
|
|||||||
return msg.getUsername();
|
return msg.getUsername();
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getPassword() {
|
public byte[] getPassword() {
|
||||||
return msg.getPassword();
|
return msg.getPassword();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -65,7 +65,7 @@ public class InterceptConnectMessage extends InterceptAbstractMessage {
|
|||||||
return msg.getWillTopic();
|
return msg.getWillTopic();
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getWillMessage() {
|
public byte[] getWillMessage() {
|
||||||
return msg.getWillMessage();
|
return msg.getWillMessage();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -177,7 +177,7 @@ class ProtocolProcessor implements EventHandler<ValueEvent> {
|
|||||||
|
|
||||||
//handle user authentication
|
//handle user authentication
|
||||||
if (msg.isUserFlag()) {
|
if (msg.isUserFlag()) {
|
||||||
String pwd = null;
|
byte[] pwd = null;
|
||||||
if (msg.isPasswordFlag()) {
|
if (msg.isPasswordFlag()) {
|
||||||
pwd = msg.getPassword();
|
pwd = msg.getPassword();
|
||||||
} else if (!this.allowAnonymous) {
|
} else if (!this.allowAnonymous) {
|
||||||
@@ -225,7 +225,7 @@ class ProtocolProcessor implements EventHandler<ValueEvent> {
|
|||||||
//Handle will flag
|
//Handle will flag
|
||||||
if (msg.isWillFlag()) {
|
if (msg.isWillFlag()) {
|
||||||
AbstractMessage.QOSType willQos = AbstractMessage.QOSType.values()[msg.getWillQos()];
|
AbstractMessage.QOSType willQos = AbstractMessage.QOSType.values()[msg.getWillQos()];
|
||||||
byte[] willPayload = msg.getWillMessage().getBytes();
|
byte[] willPayload = msg.getWillMessage();
|
||||||
ByteBuffer bb = (ByteBuffer) ByteBuffer.allocate(willPayload.length).put(willPayload).flip();
|
ByteBuffer bb = (ByteBuffer) ByteBuffer.allocate(willPayload.length).put(willPayload).flip();
|
||||||
//save the will testament in the clientID store
|
//save the will testament in the clientID store
|
||||||
WillMessage will = new WillMessage(msg.getWillTopic(), bb, msg.isWillRetain(),willQos );
|
WillMessage will = new WillMessage(msg.getWillTopic(), bb, msg.isWillRetain(),willQos );
|
||||||
|
|||||||
+1
-1
@@ -4,7 +4,7 @@ package org.eclipse.moquette.spi.impl.security;
|
|||||||
* Created by andrea on 8/23/14.
|
* Created by andrea on 8/23/14.
|
||||||
*/
|
*/
|
||||||
public class AcceptAllAuthenticator implements IAuthenticator {
|
public class AcceptAllAuthenticator implements IAuthenticator {
|
||||||
public boolean checkValid(String username, String password) {
|
public boolean checkValid(String username, byte[] password) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -106,7 +106,7 @@ public class FileAuthenticator implements IAuthenticator {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean checkValid(String username, String password) {
|
public boolean checkValid(String username, byte[] password) {
|
||||||
if (username == null || password == null) {
|
if (username == null || password == null) {
|
||||||
LOG.info("username or password was null");
|
LOG.info("username or password was null");
|
||||||
return false;
|
return false;
|
||||||
@@ -115,11 +115,7 @@ public class FileAuthenticator implements IAuthenticator {
|
|||||||
if (foundPwq == null) {
|
if (foundPwq == null) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
try {
|
m_digest.update(password);
|
||||||
m_digest.update(password.getBytes("UTF-8"));
|
|
||||||
} catch (UnsupportedEncodingException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
byte[] digest = m_digest.digest();
|
byte[] digest = m_digest.digest();
|
||||||
String encodedPasswd = new String(Hex.encodeHex(digest));
|
String encodedPasswd = new String(Hex.encodeHex(digest));
|
||||||
return foundPwq.equals(encodedPasswd);
|
return foundPwq.equals(encodedPasswd);
|
||||||
|
|||||||
@@ -22,5 +22,5 @@ package org.eclipse.moquette.spi.impl.security;
|
|||||||
*/
|
*/
|
||||||
public interface IAuthenticator {
|
public interface IAuthenticator {
|
||||||
|
|
||||||
boolean checkValid(String username, String password);
|
boolean checkValid(String username, byte[] password);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -79,7 +79,7 @@ public class ConfigurationClassLoaderTest implements IAuthenticator, IAuthorizat
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean checkValid(String username, String password) {
|
public boolean checkValid(String username, byte[] password) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -111,7 +111,7 @@ public class ServerLowlevelMessagesIntegrationTests {
|
|||||||
connectMessage.setClientID("FAKECLNT");
|
connectMessage.setClientID("FAKECLNT");
|
||||||
connectMessage.setKeepAlive(keepAlive);
|
connectMessage.setKeepAlive(keepAlive);
|
||||||
connectMessage.setWillFlag(true);
|
connectMessage.setWillFlag(true);
|
||||||
connectMessage.setWillMessage(willTestamentMsg);
|
connectMessage.setWillMessage(willTestamentMsg.getBytes());
|
||||||
connectMessage.setWillTopic(willTestamentTopic);
|
connectMessage.setWillTopic(willTestamentTopic);
|
||||||
connectMessage.setWillQos((byte) QOSType.MOST_ONE.ordinal());
|
connectMessage.setWillQos((byte) QOSType.MOST_ONE.ordinal());
|
||||||
|
|
||||||
|
|||||||
@@ -25,13 +25,13 @@ import org.eclipse.moquette.spi.impl.security.IAuthenticator;
|
|||||||
*/
|
*/
|
||||||
class MockAuthenticator implements IAuthenticator {
|
class MockAuthenticator implements IAuthenticator {
|
||||||
|
|
||||||
private Map<String, String> m_userPwds;
|
private Map<String, byte[]> m_userPwds;
|
||||||
|
|
||||||
MockAuthenticator(Map<String, String> userPwds) {
|
MockAuthenticator(Map<String, byte[]> userPwds) {
|
||||||
m_userPwds = userPwds;
|
m_userPwds = userPwds;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean checkValid(String username, String password) {
|
public boolean checkValid(String username, byte[] password) {
|
||||||
if (!m_userPwds.containsKey(username)) {
|
if (!m_userPwds.containsKey(username)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -52,9 +52,9 @@ public class ProtocolProcessorTest {
|
|||||||
final static String BAD_FORMATTED_TOPIC = "#MQTTClient";
|
final static String BAD_FORMATTED_TOPIC = "#MQTTClient";
|
||||||
|
|
||||||
final static String TEST_USER = "fakeuser";
|
final static String TEST_USER = "fakeuser";
|
||||||
final static String TEST_PWD = "fakepwd";
|
final static byte[] TEST_PWD = "fakepwd".getBytes();
|
||||||
final static String EVIL_TEST_USER = "eviluser";
|
final static String EVIL_TEST_USER = "eviluser";
|
||||||
final static String EVIL_TEST_PWD = "unsecret";
|
final static byte[] EVIL_TEST_PWD = "unsecret".getBytes();
|
||||||
|
|
||||||
final static List<InterceptHandler> EMPTY_OBSERVERS = Collections.emptyList();
|
final static List<InterceptHandler> EMPTY_OBSERVERS = Collections.emptyList();
|
||||||
final static BrokerInterceptor NO_OBSERVERS_INTERCEPTOR = new BrokerInterceptor(EMPTY_OBSERVERS);
|
final static BrokerInterceptor NO_OBSERVERS_INTERCEPTOR = new BrokerInterceptor(EMPTY_OBSERVERS);
|
||||||
@@ -164,7 +164,7 @@ public class ProtocolProcessorTest {
|
|||||||
m_sessionStore = memStorage;
|
m_sessionStore = memStorage;
|
||||||
//m_storageService.initStore();
|
//m_storageService.initStore();
|
||||||
|
|
||||||
Map<String, String> users = new HashMap<>();
|
Map<String, byte[]> users = new HashMap<>();
|
||||||
users.put(TEST_USER, TEST_PWD);
|
users.put(TEST_USER, TEST_PWD);
|
||||||
m_mockAuthenticator = new MockAuthenticator(users);
|
m_mockAuthenticator = new MockAuthenticator(users);
|
||||||
|
|
||||||
@@ -202,7 +202,7 @@ public class ProtocolProcessorTest {
|
|||||||
connMsg.setClientID("123");
|
connMsg.setClientID("123");
|
||||||
connMsg.setWillFlag(true);
|
connMsg.setWillFlag(true);
|
||||||
connMsg.setWillTopic("topic");
|
connMsg.setWillTopic("topic");
|
||||||
connMsg.setWillMessage("Topic message");
|
connMsg.setWillMessage("Topic message".getBytes());
|
||||||
|
|
||||||
|
|
||||||
//Exercise
|
//Exercise
|
||||||
|
|||||||
+3
-3
@@ -31,7 +31,7 @@ public class FileAuthenticatorTest {
|
|||||||
String file = getClass().getResource("/password_file.conf").getPath();
|
String file = getClass().getResource("/password_file.conf").getPath();
|
||||||
IAuthenticator auth = new FileAuthenticator(null, file);
|
IAuthenticator auth = new FileAuthenticator(null, file);
|
||||||
|
|
||||||
assertTrue(auth.checkValid("testuser", "passwd"));
|
assertTrue(auth.checkValid("testuser", "passwd".getBytes()));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -39,14 +39,14 @@ public class FileAuthenticatorTest {
|
|||||||
String file = getClass().getResource("/password_file.conf").getPath();
|
String file = getClass().getResource("/password_file.conf").getPath();
|
||||||
IAuthenticator auth = new FileAuthenticator(null, file);
|
IAuthenticator auth = new FileAuthenticator(null, file);
|
||||||
|
|
||||||
assertFalse(auth.checkValid("testuser2", "passwd"));
|
assertFalse(auth.checkValid("testuser2", "passwd".getBytes()));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void loadPasswordFile_verifyDirectoryRef() {
|
public void loadPasswordFile_verifyDirectoryRef() {
|
||||||
IAuthenticator auth = new FileAuthenticator("", "");
|
IAuthenticator auth = new FileAuthenticator("", "");
|
||||||
|
|
||||||
assertFalse(auth.checkValid("testuser2", "passwd"));
|
assertFalse(auth.checkValid("testuser2", "passwd".getBytes()));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -173,7 +173,7 @@ public class ConnectDecoder extends DemuxDecoder {
|
|||||||
|
|
||||||
//Decode willMessage
|
//Decode willMessage
|
||||||
if (willFlag) {
|
if (willFlag) {
|
||||||
String willMessage = Utils.decodeString(in);
|
byte[] willMessage = Utils.readFixedLengthContent(in);
|
||||||
if (willMessage == null) {
|
if (willMessage == null) {
|
||||||
in.resetReaderIndex();
|
in.resetReaderIndex();
|
||||||
return;
|
return;
|
||||||
@@ -207,7 +207,7 @@ public class ConnectDecoder extends DemuxDecoder {
|
|||||||
|
|
||||||
//Decode password
|
//Decode password
|
||||||
if (passwordFlag) {
|
if (passwordFlag) {
|
||||||
String password = Utils.decodeString(in);
|
byte[] password = Utils.readFixedLengthContent(in);
|
||||||
if (password == null) {
|
if (password == null) {
|
||||||
in.resetReaderIndex();
|
in.resetReaderIndex();
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -65,12 +65,12 @@ public class ConnectEncoder extends DemuxEncoder<ConnectMessage> {
|
|||||||
variableHeaderBuff.writeBytes(Utils.encodeString(message.getClientID()));
|
variableHeaderBuff.writeBytes(Utils.encodeString(message.getClientID()));
|
||||||
if (message.isWillFlag()) {
|
if (message.isWillFlag()) {
|
||||||
variableHeaderBuff.writeBytes(Utils.encodeString(message.getWillTopic()));
|
variableHeaderBuff.writeBytes(Utils.encodeString(message.getWillTopic()));
|
||||||
variableHeaderBuff.writeBytes(Utils.encodeString(message.getWillMessage()));
|
variableHeaderBuff.writeBytes(Utils.encodeFixedLengthContent(message.getWillMessage()));
|
||||||
}
|
}
|
||||||
if (message.isUserFlag() && message.getUsername() != null) {
|
if (message.isUserFlag() && message.getUsername() != null) {
|
||||||
variableHeaderBuff.writeBytes(Utils.encodeString(message.getUsername()));
|
variableHeaderBuff.writeBytes(Utils.encodeString(message.getUsername()));
|
||||||
if (message.isPasswordFlag() && message.getPassword() != null) {
|
if (message.isPasswordFlag() && message.getPassword() != null) {
|
||||||
variableHeaderBuff.writeBytes(Utils.encodeString(message.getPassword()));
|
variableHeaderBuff.writeBytes(Utils.encodeFixedLengthContent(message.getPassword()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -117,10 +117,16 @@ public class Utils {
|
|||||||
* @return the decoded string or null if NEED_DATA
|
* @return the decoded string or null if NEED_DATA
|
||||||
*/
|
*/
|
||||||
static String decodeString(ByteBuf in) throws UnsupportedEncodingException {
|
static String decodeString(ByteBuf in) throws UnsupportedEncodingException {
|
||||||
|
return new String(readFixedLengthContent(in), "UTF-8");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read a byte array from the buffer, use two bytes as length information followed by length bytes.
|
||||||
|
* */
|
||||||
|
static byte[] readFixedLengthContent(ByteBuf in) throws UnsupportedEncodingException {
|
||||||
if (in.readableBytes() < 2) {
|
if (in.readableBytes() < 2) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
//int strLen = Utils.readWord(in);
|
|
||||||
int strLen = in.readUnsignedShort();
|
int strLen = in.readUnsignedShort();
|
||||||
if (in.readableBytes() < strLen) {
|
if (in.readableBytes() < strLen) {
|
||||||
return null;
|
return null;
|
||||||
@@ -128,16 +134,14 @@ public class Utils {
|
|||||||
byte[] strRaw = new byte[strLen];
|
byte[] strRaw = new byte[strLen];
|
||||||
in.readBytes(strRaw);
|
in.readBytes(strRaw);
|
||||||
|
|
||||||
return new String(strRaw, "UTF-8");
|
return strRaw;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return the IoBuffer with string encoded as MSB, LSB and UTF-8 encoded
|
* Return the IoBuffer with string encoded as MSB, LSB and UTF-8 encoded
|
||||||
* string content.
|
* string content.
|
||||||
*/
|
*/
|
||||||
public static ByteBuf encodeString(String str) {
|
public static ByteBuf encodeString(String str) {
|
||||||
ByteBuf out = Unpooled.buffer(2);
|
|
||||||
byte[] raw;
|
byte[] raw;
|
||||||
try {
|
try {
|
||||||
raw = str.getBytes("UTF-8");
|
raw = str.getBytes("UTF-8");
|
||||||
@@ -147,9 +151,16 @@ public class Utils {
|
|||||||
LoggerFactory.getLogger(Utils.class).error(null, ex);
|
LoggerFactory.getLogger(Utils.class).error(null, ex);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
//Utils.writeWord(out, raw.length);
|
return encodeFixedLengthContent(raw);
|
||||||
out.writeShort(raw.length);
|
}
|
||||||
out.writeBytes(raw);
|
|
||||||
|
/**
|
||||||
|
* Return the IoBuffer with string encoded as MSB, LSB and bytes array content.
|
||||||
|
*/
|
||||||
|
public static ByteBuf encodeFixedLengthContent(byte[] content) {
|
||||||
|
ByteBuf out = Unpooled.buffer(2);
|
||||||
|
out.writeShort(content.length);
|
||||||
|
out.writeBytes(content);
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+3
-3
@@ -142,7 +142,7 @@ public class ConnectDecoderTest {
|
|||||||
verifyBaseHeader(message);
|
verifyBaseHeader(message);
|
||||||
assertEquals("ABCDEFGH", message.getClientID());
|
assertEquals("ABCDEFGH", message.getClientID());
|
||||||
assertEquals("Topic", message.getWillTopic());
|
assertEquals("Topic", message.getWillTopic());
|
||||||
assertEquals("Message", message.getWillMessage());
|
assertEquals("Message", new String(message.getWillMessage()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -167,9 +167,9 @@ public class ConnectDecoderTest {
|
|||||||
assertEquals(AbstractMessage.CONNECT, message.getMessageType());
|
assertEquals(AbstractMessage.CONNECT, message.getMessageType());
|
||||||
assertEquals("ABCDEFGH", message.getClientID());
|
assertEquals("ABCDEFGH", message.getClientID());
|
||||||
assertEquals("Topic", message.getWillTopic());
|
assertEquals("Topic", message.getWillTopic());
|
||||||
assertEquals("Message", message.getWillMessage());
|
assertEquals("Message", new String(message.getWillMessage()));
|
||||||
assertEquals("Fakeuser", message.getUsername());
|
assertEquals("Fakeuser", message.getUsername());
|
||||||
assertEquals("pwd", message.getPassword());
|
assertEquals("pwd", new String(message.getPassword()));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test(expected = CorruptedFrameException.class)
|
@Test(expected = CorruptedFrameException.class)
|
||||||
|
|||||||
+3
-3
@@ -75,7 +75,7 @@ public class ConnectEncoderTest {
|
|||||||
//variable part
|
//variable part
|
||||||
msg.setClientID("ABCDEF");
|
msg.setClientID("ABCDEF");
|
||||||
msg.setWillTopic("Topic");
|
msg.setWillTopic("Topic");
|
||||||
msg.setWillMessage("Message");
|
msg.setWillMessage("Message".getBytes());
|
||||||
|
|
||||||
ByteBuf out = Unpooled.buffer();
|
ByteBuf out = Unpooled.buffer();
|
||||||
|
|
||||||
@@ -111,9 +111,9 @@ public class ConnectEncoderTest {
|
|||||||
//variable part
|
//variable part
|
||||||
msg.setClientID("ABCDEF");
|
msg.setClientID("ABCDEF");
|
||||||
msg.setWillTopic("Topic");
|
msg.setWillTopic("Topic");
|
||||||
msg.setWillMessage("Message");
|
msg.setWillMessage("Message".getBytes());
|
||||||
msg.setUsername("Pablo");
|
msg.setUsername("Pablo");
|
||||||
msg.setPassword("PBL");
|
msg.setPassword("PBL".getBytes());
|
||||||
|
|
||||||
ByteBuf out = Unpooled.buffer();
|
ByteBuf out = Unpooled.buffer();
|
||||||
|
|
||||||
|
|||||||
+6
-6
@@ -35,10 +35,10 @@ public class ConnectMessage extends AbstractMessage {
|
|||||||
|
|
||||||
//Variable part
|
//Variable part
|
||||||
protected String m_username;
|
protected String m_username;
|
||||||
protected String m_password;
|
protected byte[] m_password;
|
||||||
protected String m_clientID;
|
protected String m_clientID;
|
||||||
protected String m_willtopic;
|
protected String m_willtopic;
|
||||||
protected String m_willMessage;
|
protected byte[] m_willMessage;
|
||||||
|
|
||||||
public ConnectMessage() {
|
public ConnectMessage() {
|
||||||
m_messageType = AbstractMessage.CONNECT;
|
m_messageType = AbstractMessage.CONNECT;
|
||||||
@@ -116,11 +116,11 @@ public class ConnectMessage extends AbstractMessage {
|
|||||||
this.m_willRetain = willRetain;
|
this.m_willRetain = willRetain;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getPassword() {
|
public byte[] getPassword() {
|
||||||
return m_password;
|
return m_password;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setPassword(String password) {
|
public void setPassword(byte[] password) {
|
||||||
this.m_password = password;
|
this.m_password = password;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -148,11 +148,11 @@ public class ConnectMessage extends AbstractMessage {
|
|||||||
this.m_willtopic = topic;
|
this.m_willtopic = topic;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getWillMessage() {
|
public byte[] getWillMessage() {
|
||||||
return m_willMessage;
|
return m_willMessage;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setWillMessage(String willMessage) {
|
public void setWillMessage(byte[] willMessage) {
|
||||||
this.m_willMessage = willMessage;
|
this.m_willMessage = willMessage;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user