Skip to content

Commit

Permalink
also prevent root wildcards for shared subscriptions
Browse files Browse the repository at this point in the history
  • Loading branch information
schaebo committed Sep 25, 2019
1 parent 6620317 commit d836c4d
Show file tree
Hide file tree
Showing 4 changed files with 58 additions and 18 deletions.
5 changes: 3 additions & 2 deletions README.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
== HiveMQ Deny Wildcard Subscription Extension
*Extension Type*: Security

*Version*: 4.0.0
*Version*: 4.1.1

*License*: Apache License 2.0

Expand All @@ -21,7 +21,8 @@ This extension denies any subscription to the root wildcard topic. In general, r
No configuration needed, works out of the box.

=== First Steps
After the extension is installed start HiveMQ. Now no client is allowed to subscribe to `#`.
After the extension is installed start HiveMQ. Now no client is allowed to subscribe to `#`, `+/#`, `$share/group/#`
or any other topic filter that would represent a root wildcard.

==== Need help?

Expand Down
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@

<groupId>com.hivemq.extension</groupId>
<artifactId>hivemq-deny-wildcard-extension</artifactId>
<version>4.1.0</version>
<version>4.1.1</version>
<description>HiveMQ Extension to deny top level wildcard subscription</description>
<inceptionYear>2018</inceptionYear>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.regex.Matcher;
import java.util.regex.Pattern;


Expand All @@ -41,7 +42,8 @@
public class DenyWildcardAuthorizer implements SubscriptionAuthorizer {

public static final DenyWildcardAuthorizer INSTANCE = new DenyWildcardAuthorizer();
public static final String REASON_STRING = "Root wildcard subscription not supported.";
public static final String REASON_STRING = "Root wildcard subscriptions are not supported.";
private static final Pattern SHARED_SUBSCRIPTION_PATTERN = Pattern.compile("\\$share(/.*?/(.*))");

private DenyWildcardAuthorizer() {
}
Expand All @@ -52,6 +54,18 @@ private DenyWildcardAuthorizer() {
@Override
public void authorizeSubscribe(@NotNull final SubscriptionAuthorizerInput subscriptionAuthorizerInput, @NotNull final SubscriptionAuthorizerOutput subscriptionAuthorizerOutput) {
final String topicFilter = subscriptionAuthorizerInput.getSubscription().getTopicFilter();

if (topicFilter.startsWith("$share/")) {
final Matcher matcher = SHARED_SUBSCRIPTION_PATTERN.matcher(topicFilter);
if (matcher.matches()) {
final String subscriptionTopic = matcher.group(2);
if (StringUtils.containsOnly(subscriptionTopic, WILDCARD_CHARS)) {
logger.debug("Client {} tried to subscribe to an denied shared root wildcard topic filter '{}'", subscriptionAuthorizerInput.getClientInformation().getClientId(), topicFilter);
subscriptionAuthorizerOutput.failAuthorization(SubackReasonCode.NOT_AUTHORIZED, REASON_STRING);
}
}
}

if (StringUtils.containsOnly(topicFilter, WILDCARD_CHARS)) {
logger.debug("Client {} tried to subscribe to an denied root wildcard topic filter '{}'", subscriptionAuthorizerInput.getClientInformation().getClientId(), topicFilter);
subscriptionAuthorizerOutput.failAuthorization(SubackReasonCode.NOT_AUTHORIZED, REASON_STRING);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,61 +63,62 @@ public void test_denied_hashtag() {
}

@Test
public void test_denied_plus() {
when(input.getSubscription().getTopicFilter()).thenReturn("+");
public void test_denied_shared_hash() {
when(input.getSubscription().getTopicFilter()).thenReturn("$share/group/#");
DenyWildcardAuthorizer.INSTANCE.authorizeSubscribe(input, output);

verify(output).failAuthorization(SubackReasonCode.NOT_AUTHORIZED, DenyWildcardAuthorizer.REASON_STRING);
}

@Test
public void test_denied_plus_slash() {
when(input.getSubscription().getTopicFilter()).thenReturn("+/");
public void test_denied_hash() {
when(input.getSubscription().getTopicFilter()).thenReturn("/#");
DenyWildcardAuthorizer.INSTANCE.authorizeSubscribe(input, output);

verify(output).failAuthorization(SubackReasonCode.NOT_AUTHORIZED, DenyWildcardAuthorizer.REASON_STRING);
}

@Test
public void test_denied_hashtag_slash() {
when(input.getSubscription().getTopicFilter()).thenReturn("#/");
public void test_denied_shared_slash_hash() {
when(input.getSubscription().getTopicFilter()).thenReturn("$share/group//#");
DenyWildcardAuthorizer.INSTANCE.authorizeSubscribe(input, output);

verify(output).failAuthorization(SubackReasonCode.NOT_AUTHORIZED, DenyWildcardAuthorizer.REASON_STRING);
}

@Test
public void test_denied_hashtag_plus() {
when(input.getSubscription().getTopicFilter()).thenReturn("#/+");
public void test_denied_plus_hash() {
when(input.getSubscription().getTopicFilter()).thenReturn("+/#");
DenyWildcardAuthorizer.INSTANCE.authorizeSubscribe(input, output);

verify(output).failAuthorization(SubackReasonCode.NOT_AUTHORIZED, DenyWildcardAuthorizer.REASON_STRING);
}

@Test
public void test_denied_plus_hashtag() {
when(input.getSubscription().getTopicFilter()).thenReturn("+/#");
public void test_denied_shared_plus_hash() {
when(input.getSubscription().getTopicFilter()).thenReturn("$share/group/+/#");
DenyWildcardAuthorizer.INSTANCE.authorizeSubscribe(input, output);

verify(output).failAuthorization(SubackReasonCode.NOT_AUTHORIZED, DenyWildcardAuthorizer.REASON_STRING);
}

@Test
public void test_denied_slash_plus() {
when(input.getSubscription().getTopicFilter()).thenReturn("/+");
public void test_denied_plus_plus() {
when(input.getSubscription().getTopicFilter()).thenReturn("+/+");
DenyWildcardAuthorizer.INSTANCE.authorizeSubscribe(input, output);

verify(output).failAuthorization(SubackReasonCode.NOT_AUTHORIZED, DenyWildcardAuthorizer.REASON_STRING);
}

@Test
public void test_denied_slash_hashtag() {
when(input.getSubscription().getTopicFilter()).thenReturn("/#");
public void test_denied_shared_plus_plus() {
when(input.getSubscription().getTopicFilter()).thenReturn("$share/group/+/+");
DenyWildcardAuthorizer.INSTANCE.authorizeSubscribe(input, output);

verify(output).failAuthorization(SubackReasonCode.NOT_AUTHORIZED, DenyWildcardAuthorizer.REASON_STRING);
}


@Test
public void test_success() {
when(input.getSubscription().getTopicFilter()).thenReturn("topic");
Expand All @@ -134,6 +135,30 @@ public void test_success_non_root_hashtag() {
verify(output).authorizeSuccessfully();
}

@Test
public void test_success_shared_non_root_wildcard() {
when(input.getSubscription().getTopicFilter()).thenReturn("$share/group/topic/#");
DenyWildcardAuthorizer.INSTANCE.authorizeSubscribe(input, output);

verify(output).authorizeSuccessfully();
}

@Test
public void test_success_non_root_plus_wildcard() {
when(input.getSubscription().getTopicFilter()).thenReturn("+/topic/#");
DenyWildcardAuthorizer.INSTANCE.authorizeSubscribe(input, output);

verify(output).authorizeSuccessfully();
}

@Test
public void test_success_shared_non_root_plus_wildcard() {
when(input.getSubscription().getTopicFilter()).thenReturn("$share/group/+/topic/#");
DenyWildcardAuthorizer.INSTANCE.authorizeSubscribe(input, output);

verify(output).authorizeSuccessfully();
}

@Test
public void test_success_non_root_plus() {
when(input.getSubscription().getTopicFilter()).thenReturn("topic/+");
Expand Down

0 comments on commit d836c4d

Please sign in to comment.