PreviousNext

Binding and Security Information

One element that is clearly missing from the context handle sample code is any access checking. To do this, it is necessary to get the client binding, although it may not be immediately obvious how to do this with a context handle. The answer is actually quite simple but, to understand it, it helps to have a clear idea of how binding parameters operate in RPC.

Every call requires binding information, whether this is supplied explicitly as a binding parameter or not. When a call is made with a binding handle, the client uses cached binding information associated with the binding handle. When no binding handle parameter is passed, the client derives the binding information it needs by some other means. For example, with a context handle, the client uses cached binding information associated with the context handle.

Even when an explicit binding handle parameter is present, the handle is not marshalled as call data in the same way other call parameters are. Similarly, on the server side, when a binding handle parameter is present in a manager operation, it is unmarshalled simply as a reference to the binding information cached by the server runtime for the call. It is irrelevant whether the call was made with an explicit binding handle parameter on the client side.

Therefore, it is perfectly possible for a server manager operation to have a binding handle as a parameter even when the client RPC call is made without an explicit binding parameter.

The mechanics of this are to use different .acf declarations on the client and server sides. The .idl file declaration for the operation does not declare an explicit binding handle parameter, but the server .acf file applies the [explicit_handle] attribute to the operation. This results in a server stub that expects to unmarshal a binding handle as the first parameter of the operation, while the client stub does not expect an explicit binding handle parameter for the call.

An example of a server-side .acf file for the store interface is as follows:

/* store.acf - server side

* Unmarshal a client binding handle on each call

*/

interface store

{

store_open();

[explicit_handle]store_close();

[explicit_handle]store_set_ptr();

[explicit_handle]store_read();

[explicit_handle]store_write();

}

You could achieve the same effect by using different .idl files for the client and server, but this is not recommended. The .idl file serves as the canonical representation of an interface and hence should be the same for all clients and servers.

This technique can be used in a number of ways; for example, to permit the client to use implicit binding while the server manager operations extract authorization information from a client binding handle. In the case of a context handle, the principle is the same. You use the server .acf declarations to add a binding parameter to the call on the server side. The client continues to call using the context handle, while the server manager receives the client binding as a first extra parameter.

In the case of the sample code, the client calls to the store interface remain the same, but the server manager implementations now contain an extra parameter. For example:

void

store_write(

handle_t IDL_handle,

store_handle_t store_h,

unsigned32 buf_size,

store_buf_t buffer,

unsigned32 *data_size,

error_status_t *status

)

{

store_spec_t *spec;

store_hdr_t *hdr;

if (check_access(IDL_handle, sec_acl_perm_write) == 0)

{

*status = str_s_no_perms;

return;

}

.

.

.

}