For Inter-ORB communication, e.g., via IIOP
, it is possible
to intercept requests and replies. To be able to use Inteceptors
Orber the configuration parameter interceptors
must be defined.
The configuration parameter interceptors
must be defined, e.g.,
as command line option:
erl -orber interceptors "{native, ['myInterceptor']}"
It is possible to use more than one interceptor; simply add them to the list and they will be invoked in the same order as they appear in the list.
One can also active and deactivate an interceptor during
run-time, but this will only affect currently existing connections.
For more information, consult Orber's Reference Manual regarding the
operations orber:activate_audit_trail/0/1
and
orber:activate_audit_trail/0/1.
Each supplied interceptor must export the following functions:
out_request
but the request body is encode.
in_request
is called.
out_reply
operation is called with the result of the object
invocation.
The operations new_out_connection
, new_in_connection
,
closed_in_connection
and closed_out_connection
operations
are only invoked once per connection. The remaining operations
are called, as shown below, for every Request/Reply to/from remote
CORBA Objects.
Assume we want to create a simple access service which purpose is to:
To restricts the access we use a protected
and named
ets-table
holding all information. How the ets-table is initiated and maintained
is implementation specific, but it contain
{Node, ObjectTable, ChecksumModule}
where Node
is used as
ets-key, ObjectTable
is a reference to another ets-table in which
we store which objects the clients are allowed to invoke operations on
and ChecksumModule
determines which module we should use to handle
the checksums.
new_in_connection(Arg, Host, Port) -> %% Since we only use one interceptor we do not care about the %% input Arg since it is set do undefined by Orber. case ets:lookup(in_access_table, Host) of [] -> %% We may want to log the Host/Port to see if someone tried %% to hack in to our system. exit("Access not granted"); [{Host, ObjTable, ChecksumModule}] -> {ObjTable, ChecksumModule} end.
The returned tuple, i.e., {ObjTable, ChecksumModule}, will be passed as the first argument whenever invoking one of the interceptor functions. Unless the connection attempt did not fail we are now ready for receiving requests from the client side ORB.
When a new request comes in the first interceptor function to be invoked is
in_request_encoded
. We will remove the checksum from the coded
request body in the following way:
in_request_encoded({ObjTable, ChecksumModule}, ObjKey, Ctx, Op, Bin, Extra) -> NewBin = ChecksumModule:remove_checksum(Bin), {NewBin, Extra}.
If the checksum check fails the ChecksumModule
should invoke exit/1.
But if the check succeeded we are now ready to check if the client-ORB
objects are allowed to invoke operations on the target object. Please note,
it is possible to run both checks in in_request_encoded
. Please
note, the chceksum calculation must be relatively fast to ensure a
good throughput.
If we want to we can restrict any clients to only use a subset of operations exported by a server:
in_request({ObjTable, ChecksumModule}, ObjKey, Ctx, Op, Params, Extra) -> case ets:lookup(ObjTable, {ObjKey, Op}) of [] -> exit("Client tried to invoke illegal operation"); [SomeData] -> {Params, Extra} end.
At this point Orber are now ready to invoke the operation on the target
object. Since we do not care about what the reply is the out_reply
function do nothing, i.e.:
out_reply(_, _, _, _, Reply, Extra) -> {Reply, Extra}.
If the client side ORB expects a checksum to be added to the reply we add it by using:
out_reply_encoded({ObjTable, ChecksumModule}, ObjKey, Ctx, Op, Bin, Extra) -> NewBin = ChecksumModule:add_checksum(Bin), {NewBin, Extra}.
![]() |
If we manipulate the binary as above the behaviour must
be |
For outgoing requests the principle is the same. Hence, it is not further described here. The complete interceptor module would look like:
-module(myInterceptor). %% Interceptor functions. -export([new_out_connection/3, new_in_connection/3, closed_in_connection/1, closed_out_connection/1, in_request_encoded/6, in_reply_encoded/6, out_reply_encoded/6, out_request_encoded/6, in_request/6, in_reply/6, out_reply/6, out_request/6]). new_in_connection(Arg, Host, Port) -> %% Since we only use one interceptor we do not care about the %% input Arg since it is set do undefined by Orber. case ets:lookup(in_access_table, Host) of [] -> %% We may want to log the Host/Port to see if someone tried %% to hack in to our system. exit("Access not granted"); [{Host, ObjTable, ChecksumModule}] -> {ObjTable, ChecksumModule} end. new_out_connection(Arg, Host, Port) -> case ets:lookup(out_access_table, Host) of [] -> exit("Access not granted"); [{Host, ObjTable, ChecksumModule}] -> {ObjTable, ChecksumModule} end. in_request_encoded({_, ChecksumModule}, ObjKey, Ctx, Op, Bin, Extra) -> NewBin = ChecksumModule:remove_checksum(Bin), {NewBin, Extra}. in_request({ObjTable, _}, ObjKey, Ctx, Op, Params, Extra) -> case ets:lookup(ObjTable, {ObjKey, Op}) of [] -> exit("Client tried to invoke illegal operation"); [SomeData] -> {Params, Extra} end. out_reply(_, _, _, _, Reply, Extra) -> {Reply, Extra}. out_reply_encoded({_, ChecksumModule}, ObjKey, Ctx, Op, Bin, Extra) -> NewBin = ChecksumModule:add_checksum(Bin), {NewBin, Extra}. out_request({ObjTable, _}, ObjKey, Ctx, Op, Params, Extra) -> case ets:lookup(ObjTable, {ObjKey, Op}) of [] -> exit("Client tried to invoke illegal operation"); [SomeData] -> {Params, Extra} end. out_request_encoded({_, ChecksumModule}, ObjKey, Ctx, Op, Bin, Extra) -> NewBin = ChecksumModule:add_checksum(Bin), {NewBin, Extra}. in_reply_encoded({_, ChecksumModule}, ObjKey, Ctx, Op, Bin, Extra) -> NewBin = ChecksumModule:remove_checksum(Bin), {NewBin, Extra}. in_reply(_, _, _, _, Reply, Extra) -> {Reply, Extra}. closed_in_connection(Arg) -> %% Nothing to clean up. Arg. closed_out_connection(Arg) -> %% Nothing to clean up. Arg.
![]() |
One can also use interceptors for debugging purposes, e.g.,
print which objects and operations are invoked with which arguments
and the outcome of the operation. In conjunction with the configuration
parameter |