diff options
| author | Matthias Radestock <matthias@lshift.net> | 2009-01-16 17:45:49 +0000 |
|---|---|---|
| committer | Matthias Radestock <matthias@lshift.net> | 2009-01-16 17:45:49 +0000 |
| commit | 4bb5b5cc0ec57db39331340eb2e60e2cc1c13249 (patch) | |
| tree | c53d7e887f5eca6184da9eb8fdc96183050f8630 /src | |
| parent | ea7885a47d3b8c2c343f12d1a81ea0a4c684122a (diff) | |
| download | rabbitmq-server-git-4bb5b5cc0ec57db39331340eb2e60e2cc1c13249.tar.gz | |
hook in permission checks
Diffstat (limited to 'src')
| -rw-r--r-- | src/rabbit_access_control.erl | 33 | ||||
| -rw-r--r-- | src/rabbit_channel.erl | 24 |
2 files changed, 55 insertions, 2 deletions
diff --git a/src/rabbit_access_control.erl b/src/rabbit_access_control.erl index 177e6f20c0..d75f1b2992 100644 --- a/src/rabbit_access_control.erl +++ b/src/rabbit_access_control.erl @@ -34,7 +34,7 @@ -include("rabbit.hrl"). -export([check_login/2, user_pass_login/2, - check_vhost_access/2]). + check_vhost_access/2, check_resource_access/3]). -export([add_user/2, delete_user/1, change_password/2, list_users/0, lookup_user/1]). -export([add_vhost/1, delete_vhost/1, list_vhosts/0, list_vhost_users/1]). @@ -47,6 +47,8 @@ -spec(check_login/2 :: (binary(), binary()) -> user()). -spec(user_pass_login/2 :: (username(), password()) -> user()). -spec(check_vhost_access/2 :: (user(), vhost()) -> 'ok'). +-spec(check_resource_access/3 :: + (username(), r(atom()), non_neg_integer()) -> 'ok'). -spec(add_user/2 :: (username(), password()) -> 'ok'). -spec(delete_user/1 :: (username()) -> 'ok'). -spec(change_password/2 :: (username(), password()) -> 'ok'). @@ -131,6 +133,35 @@ check_vhost_access(#user{username = Username}, VHostPath) -> [VHostPath, Username]) end. +check_resource_access(Username, + R = #resource{kind = exchange, name = <<"">>}, + Permission) -> + check_resource_access(Username, + R#resource{name = <<"amq.default">>}, + Permission); +check_resource_access(Username, + R = #resource{virtual_host = VHostPath, name = Name}, + Permission) -> + %% TODO: cache the results + Res = case mnesia:dirty_read({user_permission, + #user_vhost{username = Username, + virtual_host = VHostPath}}) of + [] -> + false; + [#user_permission{permission = P}] -> + case regexp:match( + binary_to_list(Name), + binary_to_list(element(Permission, P))) of + {match, _, _} -> true; + nomatch -> false + end + end, + if Res -> ok; + true -> rabbit_misc:protocol_error( + access_refused, "access to ~s refused for user '~s'", + [rabbit_misc:rs(R), Username]) + end. + add_user(Username, Password) -> R = rabbit_misc:execute_mnesia_transaction( fun () -> diff --git a/src/rabbit_channel.erl b/src/rabbit_channel.erl index ef97daa4ce..056ae649a2 100644 --- a/src/rabbit_channel.erl +++ b/src/rabbit_channel.erl @@ -199,6 +199,14 @@ return_queue_declare_ok(State, NoWait, Q) -> {reply, Reply, NewState} end. +check_configuration_permitted(Resource, #ch{ username = Username}) -> + rabbit_access_control:check_resource_access( + Username, Resource, #permission.configuration). + +check_messaging_permitted(Resource, #ch{ username = Username}) -> + rabbit_access_control:check_resource_access( + Username, Resource, #permission.messaging). + expand_queue_name_shortcut(<<>>, #ch{ most_recently_declared_queue = <<>> }) -> rabbit_misc:protocol_error( not_allowed, "no previously declared queue", []); @@ -269,6 +277,7 @@ handle_method(#'basic.publish'{exchange = ExchangeNameBin, immediate = Immediate}, Content, State = #ch{ virtual_host = VHostPath}) -> ExchangeName = rabbit_misc:r(VHostPath, exchange, ExchangeNameBin), + check_messaging_permitted(ExchangeName, State), Exchange = rabbit_exchange:lookup_or_die(ExchangeName), %% We decode the content's properties here because we're almost %% certain to want to look at delivery-mode and priority. @@ -312,6 +321,7 @@ handle_method(#'basic.get'{queue = QueueNameBin, _, State = #ch{ proxy_pid = ProxyPid, writer_pid = WriterPid, next_tag = DeliveryTag }) -> QueueName = expand_queue_name_shortcut(QueueNameBin, State), + check_messaging_permitted(QueueName, State), case rabbit_amqqueue:with_or_die( QueueName, fun (Q) -> rabbit_amqqueue:basic_get(Q, ProxyPid, NoAck) end) of @@ -347,6 +357,7 @@ handle_method(#'basic.consume'{queue = QueueNameBin, case dict:find(ConsumerTag, ConsumerMapping) of error -> QueueName = expand_queue_name_shortcut(QueueNameBin, State), + check_messaging_permitted(QueueName, State), ActualConsumerTag = case ConsumerTag of <<>> -> rabbit_misc:binstring_guid("amq.ctag"); @@ -510,6 +521,7 @@ handle_method(#'exchange.declare'{exchange = ExchangeNameBin, _, State = #ch{ virtual_host = VHostPath }) -> CheckedType = rabbit_exchange:check_type(TypeNameBin), ExchangeName = rabbit_misc:r(VHostPath, exchange, ExchangeNameBin), + check_configuration_permitted(ExchangeName, State), X = case rabbit_exchange:lookup(ExchangeName) of {ok, FoundX} -> FoundX; {error, not_found} -> @@ -529,6 +541,7 @@ handle_method(#'exchange.declare'{exchange = ExchangeNameBin, nowait = NoWait}, _, State = #ch{ virtual_host = VHostPath }) -> ExchangeName = rabbit_misc:r(VHostPath, exchange, ExchangeNameBin), + check_configuration_permitted(ExchangeName, State), X = rabbit_exchange:lookup_or_die(ExchangeName), ok = rabbit_exchange:assert_type(X, rabbit_exchange:check_type(TypeNameBin)), return_ok(State, NoWait, #'exchange.declare_ok'{}); @@ -538,6 +551,7 @@ handle_method(#'exchange.delete'{exchange = ExchangeNameBin, nowait = NoWait}, _, State = #ch { virtual_host = VHostPath }) -> ExchangeName = rabbit_misc:r(VHostPath, exchange, ExchangeNameBin), + check_configuration_permitted(ExchangeName, State), case rabbit_exchange:delete(ExchangeName, IfUnused) of {error, not_found} -> rabbit_misc:protocol_error( @@ -588,9 +602,12 @@ handle_method(#'queue.declare'{queue = QueueNameBin, Other -> check_name('queue', Other) end, QueueName = rabbit_misc:r(VHostPath, queue, ActualNameBin), + check_configuration_permitted(QueueName, State), Finish(rabbit_amqqueue:declare(QueueName, Durable, AutoDelete, Args)); - Other -> Other + Other = #amqqueue{name = QueueName} -> + check_configuration_permitted(QueueName, State), + Other end, return_queue_declare_ok(State, NoWait, Q); @@ -599,6 +616,7 @@ handle_method(#'queue.declare'{queue = QueueNameBin, nowait = NoWait}, _, State = #ch{ virtual_host = VHostPath }) -> QueueName = rabbit_misc:r(VHostPath, queue, QueueNameBin), + check_configuration_permitted(QueueName, State), Q = rabbit_amqqueue:with_or_die(QueueName, fun (Q) -> Q end), return_queue_declare_ok(State, NoWait, Q); @@ -609,6 +627,7 @@ handle_method(#'queue.delete'{queue = QueueNameBin, }, _, State) -> QueueName = expand_queue_name_shortcut(QueueNameBin, State), + check_configuration_permitted(QueueName, State), case rabbit_amqqueue:with_or_die( QueueName, fun (Q) -> rabbit_amqqueue:delete(Q, IfUnused, IfEmpty) end) of @@ -645,6 +664,7 @@ handle_method(#'queue.purge'{queue = QueueNameBin, nowait = NoWait}, _, State) -> QueueName = expand_queue_name_shortcut(QueueNameBin, State), + check_messaging_permitted(QueueName, State), {ok, PurgedMessageCount} = rabbit_amqqueue:with_or_die( QueueName, fun (Q) -> rabbit_amqqueue:purge(Q) end), @@ -694,9 +714,11 @@ binding_action(Fun, ExchangeNameBin, QueueNameBin, RoutingKey, Arguments, %% FIXME: don't allow binding to internal exchanges - %% including the one named "" ! QueueName = expand_queue_name_shortcut(QueueNameBin, State), + check_configuration_permitted(QueueName, State), ActualRoutingKey = expand_routing_key_shortcut(QueueNameBin, RoutingKey, State), ExchangeName = rabbit_misc:r(VHostPath, exchange, ExchangeNameBin), + check_configuration_permitted(ExchangeName, State), case Fun(ExchangeName, QueueName, ActualRoutingKey, Arguments) of {error, queue_not_found} -> rabbit_misc:protocol_error( |
