Added handling of allow_anonymous, fix issue #34

This commit is contained in:
andrea
2015-04-25 19:49:41 +02:00
parent 966e6399f6
commit 9d8e9df44e
9 changed files with 85 additions and 18 deletions
+1
View File
@@ -10,6 +10,7 @@ Version 0.7:
Added store path variable "persistent_store" to configuration file (picked from Steven Warwick fork)
Removed OSGi bundle, developer time burner
Fixed github issue #30, returning error on mapdb file not deleted that corrupt reiterated builds
Added handling of allow_anonymous clients (as in mosquitto issue #34)
Version 0.6:
Fix issue #42, bad password file path composition
+4
View File
@@ -12,3 +12,7 @@ websocket_port 8080
host 0.0.0.0
password_file config/password_file.conf
#false to accept only client connetions with credentials
#true to accept client connection without credentails, validating only the one that provides
allow_anonymous true
@@ -59,6 +59,7 @@ class ConfigurationParser {
m_properties.put(WEB_SOCKET_PORT_PROPERTY_NAME, Integer.toString(WEBSOCKET_PORT));
m_properties.put(PASSWORD_FILE_PROPERTY_NAME, "");
m_properties.put(PERSISTENT_STORE_PROPERTY_NAME, DEFAULT_PERSISTENT_PATH);
m_properties.put(ALLOW_ANONYMOUS, true);
}
/**
@@ -97,6 +97,7 @@ class ProtocolProcessor implements EventHandler<ValueEvent> {
private Map<String, ConnectionDescriptor> m_clientIDs = new HashMap<>();
private SubscriptionsStore subscriptions;
private boolean allowAnonymous;
private IMessagesStore m_messagesStore;
private ISessionsStore m_sessionsStore;
private IAuthenticator m_authenticator;
@@ -114,13 +115,16 @@ class ProtocolProcessor implements EventHandler<ValueEvent> {
* @param storageService the persistent store to use for save/load of messages
* for QoS1 and QoS2 handling.
* @param sessionsStore the clients sessions store, used to persist subscriptions.
* @param authenticator the authenticator used in connect messages
* @param authenticator the authenticator used in connect messages.
* @param allowAnonymous true connection to clients without credentials.
*/
void init(SubscriptionsStore subscriptions, IMessagesStore storageService,
ISessionsStore sessionsStore,
IAuthenticator authenticator) {
IAuthenticator authenticator,
boolean allowAnonymous) {
//m_clientIDs = clientIDs;
this.subscriptions = subscriptions;
this.allowAnonymous = allowAnonymous;
LOG.debug("subscription tree on init {}", subscriptions.dumpTree());
m_authenticator = authenticator;
m_messagesStore = storageService;
@@ -199,13 +203,17 @@ class ProtocolProcessor implements EventHandler<ValueEvent> {
String pwd = null;
if (msg.isPasswordFlag()) {
pwd = msg.getPassword();
}
if (!m_authenticator.checkValid(msg.getUsername(), pwd)) {
ConnAckMessage okResp = new ConnAckMessage();
okResp.setReturnCode(ConnAckMessage.BAD_USERNAME_OR_PASSWORD);
session.write(okResp);
} else if (!this.allowAnonymous) {
failedCredetials(session);
return;
}
if (!m_authenticator.checkValid(msg.getUsername(), pwd)) {
failedCredetials(session);
return;
}
} else if (!this.allowAnonymous) {
failedCredetials(session);
return;
}
subscriptions.activate(msg.getClientID());
@@ -233,6 +241,12 @@ class ProtocolProcessor implements EventHandler<ValueEvent> {
}
}
private void failedCredetials(ServerChannel session) {
ConnAckMessage okResp = new ConnAckMessage();
okResp.setReturnCode(ConnAckMessage.BAD_USERNAME_OR_PASSWORD);
session.write(okResp);
}
/**
* Republish QoS1 and QoS2 messages stored into the session for the clientID.
* */
@@ -42,6 +42,7 @@ import java.util.concurrent.TimeUnit;
import static org.eclipse.moquette.commons.Constants.PASSWORD_FILE_PROPERTY_NAME;
import static org.eclipse.moquette.commons.Constants.PERSISTENT_STORE_PROPERTY_NAME;
import static org.eclipse.moquette.commons.Constants.ALLOW_ANONYMOUS;
/**
*
@@ -187,7 +188,7 @@ public class SimpleMessaging implements IMessaging, EventHandler<ValueEvent> {
//List<Subscription> storedSubscriptions = m_sessionsStore.listAllSubscriptions();
//subscriptions.init(storedSubscriptions);
subscriptions.init(m_sessionsStore);
String passwdPath = props.getProperty(PASSWORD_FILE_PROPERTY_NAME, "");
String configPath = System.getProperty("moquette.path", null);
IAuthenticator authenticator;
@@ -196,8 +197,9 @@ public class SimpleMessaging implements IMessaging, EventHandler<ValueEvent> {
} else {
authenticator = new FileAuthenticator(configPath, passwdPath);
}
m_processor.init(subscriptions, m_storageService, m_sessionsStore, authenticator);
boolean allowAnonymous = Boolean.parseBoolean(props.getProperty(ALLOW_ANONYMOUS, "true"));
m_processor.init(subscriptions, m_storageService, m_sessionsStore, authenticator, allowAnonymous);
}
@@ -164,7 +164,7 @@ public class ProtocolProcessorTest {
subscriptions = new SubscriptionsStore();
subscriptions.init(new MemoryStorageService());
m_processor = new ProtocolProcessor();
m_processor.init(subscriptions, m_storageService, m_sessionStore, m_mockAuthenticator);
m_processor.init(subscriptions, m_storageService, m_sessionStore, m_mockAuthenticator, true);
}
@Test
@@ -251,6 +251,44 @@ public class ProtocolProcessorTest {
//Verify
assertEquals(ConnAckMessage.BAD_USERNAME_OR_PASSWORD, m_returnCode);
}
@Test
public void prohibitAnonymousClient() {
connMsg.setClientID("123");
m_processor.init(subscriptions, m_storageService, m_sessionStore, m_mockAuthenticator, false);
//Exercise
m_processor.processConnect(m_session, connMsg);
//Verify
assertEquals(ConnAckMessage.BAD_USERNAME_OR_PASSWORD, m_returnCode);
}
@Test
public void prohibitAnonymousClient_providingUsername() {
connMsg.setClientID("123");
connMsg.setUserFlag(true);
connMsg.setUsername(TEST_USER + "_fake");
m_processor.init(subscriptions, m_storageService, m_sessionStore, m_mockAuthenticator, false);
//Exercise
m_processor.processConnect(m_session, connMsg);
//Verify
assertEquals(ConnAckMessage.BAD_USERNAME_OR_PASSWORD, m_returnCode);
}
@Test
public void acceptAnonymousClient() {
connMsg.setClientID("123");
m_processor.init(subscriptions, m_storageService, m_sessionStore, m_mockAuthenticator, true);
//Exercise
m_processor.processConnect(m_session, connMsg);
//Verify
assertEquals(ConnAckMessage.CONNECTION_ACCEPTED, m_returnCode);
}
@Test
@@ -298,7 +336,7 @@ public class ProtocolProcessorTest {
//simulate a connect that register a clientID to an IoSession
subs.init(new MemoryStorageService());
m_processor.init(subs, m_storageService, m_sessionStore, null);
m_processor.init(subs, m_storageService, m_sessionStore, null, true);
ConnectMessage connectMessage = new ConnectMessage();
connectMessage.setProcotolVersion((byte)3);
connectMessage.setClientID(FAKE_CLIENT_ID);
@@ -342,7 +380,7 @@ public class ProtocolProcessorTest {
//simulate a connect that register a clientID to an IoSession
subs.init(new MemoryStorageService());
m_processor.init(subs, m_storageService, m_sessionStore, null);
m_processor.init(subs, m_storageService, m_sessionStore, null, true);
MockReceiverChannel firstReceiverSession = new MockReceiverChannel();
ConnectMessage connectMessage = new ConnectMessage();
@@ -460,7 +498,7 @@ public class ProtocolProcessorTest {
subs.init(new MemoryStorageService());
//simulate a connect that register a clientID to an IoSession
m_processor.init(subs, m_storageService, m_sessionStore, null);
m_processor.init(subs, m_storageService, m_sessionStore, null, true);
ConnectMessage connectMessage = new ConnectMessage();
connectMessage.setClientID(FAKE_PUBLISHER_ID);
connectMessage.setProcotolVersion((byte)3);
@@ -499,7 +537,7 @@ public class ProtocolProcessorTest {
ByteBuffer.wrap("Hello".getBytes()), true, FAKE_PUBLISHER_ID, 120);
m_storageService.storePublishForFuture(retainedMessage);
m_processor.init(subs, m_storageService, m_sessionStore, null);
m_processor.init(subs, m_storageService, m_sessionStore, null, true);
ConnectMessage connectMessage = new ConnectMessage();
connectMessage.setClientID(FAKE_PUBLISHER_ID);
connectMessage.setProcotolVersion((byte)3);
@@ -518,7 +556,7 @@ public class ProtocolProcessorTest {
List<Subscription> inactiveSubscriptions = Arrays.asList(inactiveSub);
when(mockedSubscriptions.matches(eq("/topic"))).thenReturn(inactiveSubscriptions);
m_processor = new ProtocolProcessor();
m_processor.init(mockedSubscriptions, m_storageService, m_sessionStore, null);
m_processor.init(mockedSubscriptions, m_storageService, m_sessionStore, null, true);
//Exercise
ByteBuffer buffer = ByteBuffer.allocate(5).put("Hello".getBytes());
@@ -543,7 +581,7 @@ public class ProtocolProcessorTest {
List<Subscription> inactiveSubscriptions = Arrays.asList(inactiveSub);
when(mockedSubscriptions.matches(eq("/topic"))).thenReturn(inactiveSubscriptions);
m_processor = new ProtocolProcessor();
m_processor.init(mockedSubscriptions, m_storageService, m_sessionStore, null);
m_processor.init(mockedSubscriptions, m_storageService, m_sessionStore, null, true);
//Exercise
ByteBuffer buffer = ByteBuffer.allocate(5).put("Hello".getBytes());
@@ -611,7 +649,7 @@ public class ProtocolProcessorTest {
/*SubscriptionsStore subs = new SubscriptionsStore();
subs.init(new MemoryStorageService());*/
SubscriptionsStore subs = mock(SubscriptionsStore.class);
m_processor.init(subs, m_storageService, m_sessionStore, null);
m_processor.init(subs, m_storageService, m_sessionStore, null, true);
//simulate a connect from client1 FAKE_CLIENT_ID from channel1
ConnectMessage connectMessage = new ConnectMessage();
@@ -18,3 +18,5 @@ ssl_port 8883
jks_path serverkeystore.jks
key_store_password passw0rdsrv
key_manager_password passw0rdsrv
allow_anonymous true
@@ -13,3 +13,7 @@ host 0.0.0.0
#Password file
password_file config/password_file.conf
#false to accept only client connetions with credentials
#true to accept client connection without credentails, validating only the one that provides
allow_anonymous true
@@ -36,4 +36,5 @@ public class Constants {
public static final String JKS_PATH_PROPERTY_NAME = "jks_path";
public static final String KEY_STORE_PASSWORD_PROPERTY_NAME = "key_store_password";
public static final String KEY_MANAGER_PASSWORD_PROPERTY_NAME = "key_manager_password";
public static final String ALLOW_ANONYMOUS = "allow_anonymous";
}