Skip to content

Commit 62943cc

Browse files
committed
More efficient auth subscribe handling
1 parent fa10473 commit 62943cc

File tree

3 files changed

+43
-6
lines changed

3 files changed

+43
-6
lines changed

include/mqtt/broker/broker.hpp

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2062,12 +2062,19 @@ class broker_t {
20622062
publish_options pubopts,
20632063
v5::properties props
20642064
) {
2065+
// Get auth rights for this topic
2066+
auto auth_users = security.auth_sub(std::string(topic));
20652067

20662068
// publish the message to subscribers.
20672069
// retain is delivered as the original only if rap_value is rap::retain.
20682070
// On MQTT v3.1.1, rap_value is always rap::dont.
20692071
auto deliver =
2070-
[&] (session_state& ss, subscription& sub) {
2072+
[&] (session_state& ss, subscription& sub, auto const& auth_users) {
2073+
2074+
// See if this session is authorized to subscribe this topic
2075+
auto allowed = security.auth_sub_user(auth_users, ss.get_username());
2076+
if (allowed != security::authorization::type::allow) return;
2077+
20712078
publish_options new_pubopts = std::min(pubopts.get_qos(), sub.subopts.get_qos());
20722079
if (sub.subopts.get_rap() == rap::retain && pubopts.get_retain() == MQTT_NS::retain::yes) {
20732080
new_pubopts |= MQTT_NS::retain::yes;
@@ -2110,15 +2117,15 @@ class broker_t {
21102117
// publisher is the same as subscriber, then skip it.
21112118
if (sub.subopts.get_nl() == nl::yes &&
21122119
sub.ss.get().client_id() == source_ss.client_id()) return;
2113-
deliver(sub.ss.get(), sub);
2120+
deliver(sub.ss.get(), sub, auth_users);
21142121
}
21152122
else {
21162123
// Shared subscriptions
21172124
bool inserted;
21182125
std::tie(std::ignore, inserted) = sent.emplace(sub.share_name, sub.topic_filter);
21192126
if (inserted) {
21202127
if (auto ssr_opt = shared_targets_.get_target(sub.share_name, sub.topic_filter)) {
2121-
deliver(ssr_opt.value().get(), sub);
2128+
deliver(ssr_opt.value().get(), sub, auth_users);
21222129
}
21232130
}
21242131
}

include/mqtt/broker/security.hpp

Lines changed: 29 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ struct security
4747
{
4848
std::string topic;
4949
enum class type {
50-
allow, deny
50+
deny, allow
5151
};
5252

5353
type type_;
@@ -70,7 +70,9 @@ struct security
7070
std::map<std::string, authorization> authorization_;
7171
MQTT_NS::optional<std::string> anonymous;
7272

73-
MQTT_NS::broker::multiple_subscription_map<std::string, authorization::type> auth_pub_map;
73+
using auth_map_type = MQTT_NS::broker::multiple_subscription_map<std::string, authorization::type>;
74+
auth_map_type auth_pub_map;
75+
auth_map_type auth_sub_map;
7476

7577
MQTT_NS::optional<std::string> login_anonymous() {
7678
return anonymous;
@@ -118,6 +120,14 @@ struct security
118120
for(auto const &i: security.authorization_) {
119121
for(auto const& j: i.second.sub) {
120122
validate_entry(security, "topic " + i.first, j);
123+
124+
if(is_valid_user_name(j)) {
125+
security.auth_sub_map.insert_or_assign(i.first, j, i.second.type_);
126+
}
127+
else if(is_valid_group_name(j)) {
128+
for(auto const& z: security.groups_[j].members)
129+
security.auth_sub_map.insert_or_assign(i.first, z, i.second.type_);
130+
}
121131
}
122132
for(auto const& j: i.second.pub) {
123133
validate_entry(security, "topic " + i.first, j);
@@ -198,7 +208,7 @@ struct security
198208
validate(security);
199209
}
200210

201-
authorization::type auth_pub(std::string const& topic, std::string const& username) {
211+
authorization::type auth_pub(std::string const& topic, std::string const& username) const {
202212
authorization::type result_type = authorization::type::deny;
203213

204214
auth_pub_map.find(topic, [&](std::string const &allowed_username, authorization::type type) {
@@ -207,6 +217,22 @@ struct security
207217

208218
return result_type;
209219
}
220+
221+
std::map<std::string, authorization::type> auth_sub(std::string const& topic) const {
222+
std::map<std::string, authorization::type> result;
223+
224+
auth_sub_map.find(topic, [&](std::string const &allowed_username, authorization::type type) {
225+
result[allowed_username] = type;
226+
});
227+
228+
return result;
229+
}
230+
231+
static authorization::type auth_sub_user(std::map<std::string, authorization::type> const& result, std::string const& username) {
232+
auto i = result.find(username);
233+
if(i == result.end()) return authorization::type::deny;
234+
return i->second;
235+
}
210236
};
211237

212238
MQTT_BROKER_NS_END

test/unit/ut_broker_security.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,10 @@ BOOST_AUTO_TEST_CASE(check_publish) {
9999
BOOST_CHECK(security.auth_pub("sub/topic", "u1") == MQTT_NS::broker::security::authorization::type::allow);
100100
BOOST_CHECK(security.auth_pub("sub/topic1", "u1") == MQTT_NS::broker::security::authorization::type::deny);
101101

102+
BOOST_CHECK(security.auth_sub_user(security.auth_sub("topic"), "u1") == MQTT_NS::broker::security::authorization::type::deny);
103+
BOOST_CHECK(security.auth_sub_user(security.auth_sub("sub/topic"), "u1") == MQTT_NS::broker::security::authorization::type::allow);
104+
BOOST_CHECK(security.auth_sub_user(security.auth_sub("sub/topic1"), "u1") == MQTT_NS::broker::security::authorization::type::deny);
105+
102106
}
103107

104108
BOOST_AUTO_TEST_SUITE_END()

0 commit comments

Comments
 (0)