Moved read authorization check from publish phase to subscribe
This commit is contained in:
@@ -487,13 +487,7 @@ public class ProtocolProcessor {
|
|||||||
}
|
}
|
||||||
Channel channel = m_clientIDs.get(clientId).channel;
|
Channel channel = m_clientIDs.get(clientId).channel;
|
||||||
LOG.debug("Session for clientId {} is {}", clientId, channel);
|
LOG.debug("Session for clientId {} is {}", clientId, channel);
|
||||||
|
channel.writeAndFlush(pubMessage);
|
||||||
String user = NettyUtils.userName(channel);
|
|
||||||
if (!m_authorizator.canRead(topic, user, clientId)) {
|
|
||||||
LOG.debug("topic {} doesn't have read credentials", topic);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
channel.writeAndFlush(pubMessage); //Or writeAdnFlush but flush is costly!!
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void sendPubRec(String clientID, int messageID) {
|
private void sendPubRec(String clientID, int messageID) {
|
||||||
@@ -662,11 +656,18 @@ public class ProtocolProcessor {
|
|||||||
SubAckMessage ackMessage = new SubAckMessage();
|
SubAckMessage ackMessage = new SubAckMessage();
|
||||||
ackMessage.setMessageID(msg.getMessageID());
|
ackMessage.setMessageID(msg.getMessageID());
|
||||||
|
|
||||||
|
String user = NettyUtils.userName(channel);
|
||||||
List<Subscription> newSubscriptions = new ArrayList<>();
|
List<Subscription> newSubscriptions = new ArrayList<>();
|
||||||
for (SubscribeMessage.Couple req : msg.subscriptions()) {
|
for (SubscribeMessage.Couple req : msg.subscriptions()) {
|
||||||
|
if (!m_authorizator.canRead(req.getTopicFilter(), user, clientSession.clientID)) {
|
||||||
|
//send SUBACK with 0x80, the user hasn't credentials to read the topic
|
||||||
|
LOG.debug("topic {} doesn't have read credentials", req.getTopicFilter());
|
||||||
|
ackMessage.addType( AbstractMessage.QOSType.FAILURE);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
AbstractMessage.QOSType qos = AbstractMessage.QOSType.valueOf(req.getQos());
|
AbstractMessage.QOSType qos = AbstractMessage.QOSType.valueOf(req.getQos());
|
||||||
Subscription newSubscription = new Subscription(clientID, req.getTopicFilter(), qos);
|
Subscription newSubscription = new Subscription(clientID, req.getTopicFilter(), qos);
|
||||||
//boolean valid = subscribeSingleTopic(newSubscription, req.getTopicFilter());
|
|
||||||
boolean valid = clientSession.subscribe(req.getTopicFilter(), newSubscription);
|
boolean valid = clientSession.subscribe(req.getTopicFilter(), newSubscription);
|
||||||
ackMessage.addType(valid ? qos : AbstractMessage.QOSType.FAILURE);
|
ackMessage.addType(valid ? qos : AbstractMessage.QOSType.FAILURE);
|
||||||
if (valid) {
|
if (valid) {
|
||||||
|
|||||||
@@ -28,6 +28,7 @@ import io.moquette.spi.ISessionsStore;
|
|||||||
import io.moquette.spi.impl.security.PermitAllAuthorizator;
|
import io.moquette.spi.impl.security.PermitAllAuthorizator;
|
||||||
import io.moquette.spi.impl.subscriptions.Subscription;
|
import io.moquette.spi.impl.subscriptions.Subscription;
|
||||||
import io.moquette.spi.impl.subscriptions.SubscriptionsStore;
|
import io.moquette.spi.impl.subscriptions.SubscriptionsStore;
|
||||||
|
import io.moquette.spi.security.IAuthorizator;
|
||||||
import io.netty.channel.embedded.EmbeddedChannel;
|
import io.netty.channel.embedded.EmbeddedChannel;
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
@@ -220,6 +221,32 @@ public class ProtocolProcessorTest {
|
|||||||
Subscription expectedSubscription = new Subscription(FAKE_CLIENT_ID, FAKE_TOPIC, AbstractMessage.QOSType.MOST_ONE);
|
Subscription expectedSubscription = new Subscription(FAKE_CLIENT_ID, FAKE_TOPIC, AbstractMessage.QOSType.MOST_ONE);
|
||||||
assertTrue(subscriptions.contains(expectedSubscription));
|
assertTrue(subscriptions.contains(expectedSubscription));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSubscribedToNotAuthorizedTopic() {
|
||||||
|
final String fakeUserName = "UnAuthUser";
|
||||||
|
NettyUtils.userName(m_channel, fakeUserName);
|
||||||
|
|
||||||
|
IAuthorizator mockAuthorizator = mock(IAuthorizator.class);
|
||||||
|
when(mockAuthorizator.canRead(eq(FAKE_TOPIC), eq(fakeUserName), eq(FAKE_CLIENT_ID))).thenReturn(false);
|
||||||
|
m_processor.init(subscriptions, m_messagesStore, m_sessionStore, m_mockAuthenticator, true,
|
||||||
|
mockAuthorizator, NO_OBSERVERS_INTERCEPTOR);
|
||||||
|
|
||||||
|
//Exercise
|
||||||
|
SubscribeMessage msg = new SubscribeMessage();
|
||||||
|
msg.addSubscription(new SubscribeMessage.Couple(AbstractMessage.QOSType.MOST_ONE.byteValue(), FAKE_TOPIC));
|
||||||
|
NettyUtils.clientID(m_channel, FAKE_CLIENT_ID);
|
||||||
|
NettyUtils.cleanSession(m_channel, false);
|
||||||
|
m_sessionStore.createNewSession(FAKE_CLIENT_ID, false);
|
||||||
|
m_processor.processSubscribe(m_channel, msg);
|
||||||
|
|
||||||
|
//Verify
|
||||||
|
Object ackMsg = m_channel.readOutbound();
|
||||||
|
assertTrue(ackMsg instanceof SubAckMessage);
|
||||||
|
SubAckMessage subAckMsg = (SubAckMessage) ackMsg;
|
||||||
|
assertEquals(1, subAckMsg.types().size());
|
||||||
|
assertTrue(subAckMsg.types().contains(AbstractMessage.QOSType.FAILURE));
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testDoubleSubscribe() {
|
public void testDoubleSubscribe() {
|
||||||
|
|||||||
@@ -42,7 +42,7 @@ public class SubscribeMessage extends MessageIDMessage {
|
|||||||
return m_topicFilter;
|
return m_topicFilter;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
private List<Couple> m_subscriptions = new ArrayList<Couple>();
|
private List<Couple> m_subscriptions = new ArrayList<>();
|
||||||
|
|
||||||
public SubscribeMessage() {
|
public SubscribeMessage() {
|
||||||
//Subscribe has always QoS 1
|
//Subscribe has always QoS 1
|
||||||
|
|||||||
@@ -2,9 +2,7 @@
|
|||||||
|
|
||||||
import org.fusesource.mqtt.client.BlockingConnection
|
import org.fusesource.mqtt.client.BlockingConnection
|
||||||
import org.fusesource.mqtt.client.MQTT
|
import org.fusesource.mqtt.client.MQTT
|
||||||
import org.fusesource.mqtt.client.Message
|
|
||||||
import org.fusesource.mqtt.client.QoS
|
import org.fusesource.mqtt.client.QoS
|
||||||
import org.fusesource.mqtt.client.Topic
|
|
||||||
|
|
||||||
|
|
||||||
String host = args[0]
|
String host = args[0]
|
||||||
@@ -12,6 +10,7 @@ String topic = "/topic"
|
|||||||
if (args.length > 1) {
|
if (args.length > 1) {
|
||||||
topic = args[1]
|
topic = args[1]
|
||||||
}
|
}
|
||||||
|
println "publish script to topic ${topic} on host ${host}"
|
||||||
//start a publisher
|
//start a publisher
|
||||||
MQTT mqtt2 = new MQTT()
|
MQTT mqtt2 = new MQTT()
|
||||||
mqtt2.setHost(host, 1883)
|
mqtt2.setHost(host, 1883)
|
||||||
|
|||||||
Reference in New Issue
Block a user