Previous section.

DCE 1.1: Authentication and Security Services
Copyright © 1997 The Open Group

ACL Editor RPC Interface

This chapter specifies the RPC interface supporting ACL Editors, namely the rdacl RPC interface (the corresponding sec_acl API is specified in Access Control List API ). Recall that, by definition, "ACL Editors" are just RPC clients that invoke the operations defined in this chapter to access and manipulate (via the RPC server and its ACL managers) the ACLs on protected objects, without actually accessing the protected objects themselves.

Required background for this chapter appears in ACL Editors , Access Control Lists (ACLs) and ACL Managers .

The rdacl RPC Interface

This section specifies (in IDL/NDR) the rdacl RPC interface. All servers that support protected objects must export this RPC interface in order for ACL Editors to be able to manage their ACLs. They must also, of course, protect it (at a level consistent with the policy of the server) in order to guarantee the security of the server's ACLs and protected objects (see Protected RPC for generalities on Protected RPC, and see the required rights specifications on the rdacl operations below).

This section begins with some remarks about identifying protected objects and ACLs, followed by definitions of some common data types, and the rdacl interface interspersed with commentary explaining it.

Identifying Protected Objects and ACLs

The rdacl interface represents references to ACLs by a 4-tuple of data items, namely:

A consistent notation for these items is used throughout this section, namely (in the order listed above):

handle_t rpc_handle; sec_acl_component_name_t component_name; uuid_t *manager_type; sec_acl_type_t acl_type;

This identification scheme implies that servers supporting the rdacl interface must uniquely identify all their ACLs by means of such a 4-tuple. Within this constraint, however, the server's management of its protected objects and ACLs is not further specified here, so is application-specific.

Note:
Typically, it is the case that the first 2 of the above items (rpc_handle, component_name) together uniquely identify the protected object itself, and the last 2 items (manager_type, acl_type) together uniquely identify a particular ACL associated with that protected object. However, this is not a requirement. For example, it is conceivable (though atypical) that a server (identified by rpc_handle) could support more than one protected object having the same stringname (component_name), provided those were disambiguated (for ACL editing purposes) by being protected by ACL managers of different type UUIDs (manager_type). Again, it is entirely conceivable that a server could support protected objects that are uniquely identified by stringname (component_name), but having more than one ACL per object (these being disambiguated by their manager_types). This latter is the case of so-called "polymorphic types", and is especially useful when the server supports a hierarchical namespace whose internal nodes are not only "mere" directories but also participate in some other role (such as a directory that participates in some of the qualities of a leaf node).

Common Data Types and Constants for rdacl Interface

This section specifies (in IDL/NDR) common data types and constants used by the rdacl interface (additional data types not defined in this chapter are defined in preceding chapters and in the referenced Open Group DCE 1.1 RPC Specification).

sec_acl_component_name_t

The sec_acl_component_name_t data type is a string for "further identifying" (in an application-specific manner) a protected object (and hence its ACL)-see Identifying Protected Objects and ACLs . Its character elements are to be drawn from the Portable Character Set (see Appendix G, Portable Character Set, of the referenced Open Group DCE 1.1 RPC Specification).

typedef [string, ptr] unsigned char *sec_acl_component_name_t;
sec_acl_p_t

The sec_acl_p_t data type represents a pointer to an ACL.

typedef [ptr] sec_acl_t *sec_acl_p_t;
sec_acl_list_t

The sec_acl_list_t data type represents a list (array) of (pointers to) ACLs.

typedef struct { unsigned32 count; [size_is(count)] sec_acl_p_t sec_acls[]; } sec_acl_list_t;
sec_acl_result_t

The sec_acl_result_t data type represents a "performance-optimised" version of the sec_acl_list_t data type. In the success case (status = error_status_ok), sec_acl_result_t represents a (pointer to a) value of type sec_acl_list_t; in the error case (status != error_status_ok) it is empty (thereby preventing unnecessary marshalling/unmarshalling of data in the error case).

typedef union switch (error_status_t status) { case error_status_ok: [ptr] sec_acl_list_t acl_list; default: /*empty*/ /*empty*/; } sec_acl_result_t;
sec_acl_twr_ref_t

The sac_acl_twr_ref_t data type represents a pointer to an RPC protocol tower (twr_t, defined in Appendix L, Protocol Tower Encoding, of the referenced Open Group DCE 1.1 RPC Specification).

typedef [ref] twr_t *sec_acl_twr_ref_t;
sec_acl_tower_set_t

The sec_acl_tower_set_t data type represents a pointer to a list of (pointers to) RPC protocol towers.

typedef [ptr] struct { unsigned32 count; [size_is(count)] sec_acl_twr_ref_t towers[]; } *sec_acl_tower_set_t;
sec_acl_posix_semantics_t

The sec_acl_posix_semantics_t data type is a flag word indicating the extent of POSIX semantics supported by an ACL manager.

typedef unsigned32 sec_acl_posix_semantics_t; const sec_acl_posix_semantics_t sec_acl_posix_no_semantics = 0x00000000; const sec_acl_posix_semantics_t sec_acl_posix_mask_obj = 0x00000001;

The following values are currently registered:

Note:
Arguably, DCE "should" support a sec_acl_semantics_t flag word data type, encompassing "all" kinds of semantics, not just those related to POSIX. Such support is for future study. For the time being, DCE restricts itself to "POSIX-like" semantics, and the intention is that the bits of the sec_acl_posix_semantics_t indicate various "levels" or "flavours" of POSIX-like semantics.
Status Codes

The following status codes (transmitted as values of the type error_status_t) are specified for the rdacl interface. Only their values are specified here-their use is specified in context elsewhere in this specification.

const unsigned32  sec_acl_not_implemented        = 0x17122016;
const unsigned32  sec_acl_cant_allocate_memory   = 0x17122017;
const unsigned32  sec_acl_invalid_site_name      = 0x17122018;
const unsigned32  sec_acl_unknown_manager_type   = 0x17122019;
const unsigned32  sec_acl_object_not_found       = 0x1712201a;
const unsigned32  sec_acl_no_acl_found           = 0x1712201b;
const unsigned32  sec_acl_invalid_entry_name     = 0x1712201c;
const unsigned32  sec_acl_expected_user_obj      = 0x1712201d;
const unsigned32  sec_acl_expected_group_obj     = 0x1712201e;
const unsigned32  sec_acl_invalid_entry_type     = 0x1712201f;
const unsigned32  sec_acl_invalid_acl_type       = 0x17122020;
const unsigned32  sec_acl_bad_key                = 0x17122021;
const unsigned32  sec_acl_invalid_manager_type   = 0x17122022;
const unsigned32  sec_acl_read_only              = 0x17122023;
const unsigned32  sec_acl_site_read_only         = 0x17122024;
const unsigned32  sec_acl_invalid_permission     = 0x17122025;
const unsigned32  sec_acl_bad_acl_syntax         = 0x17122026;
const unsigned32  sec_acl_no_owner               = 0x17122027;
const unsigned32  sec_acl_invalid_entry_class    = 0x17122028;
const unsigned32  sec_acl_unable_to_authenticate = 0x17122029;
const unsigned32  sec_acl_name_resolution_failed = 0x1712202a;
const unsigned32  sec_acl_rpc_error              = 0x1712202b;
const unsigned32  sec_acl_bind_error             = 0x1712202c;
const unsigned32  sec_acl_invalid_acl_handle     = 0x1712202d;
const unsigned32  sec_acl_no_update_sites        = 0x1712202e;
const unsigned32  sec_acl_missing_required_entry = 0x17122030;
const unsigned32  sec_acl_duplicate_entry        = 0x17122031;
const unsigned32  sec_acl_bad_parameter          = 0x17122032;
const unsigned32  sec_acl_not_authorized         = 0x17122033;
const unsigned32  sec_acl_server_bad_state       = 0x17122034;
const unsigned32  sec_acl_invalid_dfs_acl        = 0x17122035;
const unsigned32  sec_acl_bad_permset            = 0x17122037;

Interface UUID and Version Number for rdacl Interface

The interface UUID and version number for the rdacl interface are given by the following:

[uuid(47b33331-8000-0000-0d00-01dc6c000000), version(0.0)] interface rdacl { /* begin running listing of rdacl interface */
Implementation Variability Regarding Required Rights

The RPC (rdacl) operations specified in this chapter are intended to be implemented by various kinds of servers, whose detailed specification is in general beyond the scope of this specification, and all of whose security requirements cannot therefore be anticipated by DCE. In particular, the authorisation policies ("required rights") to the server's ACLs are the responsibility of the server itself (or more precisely, of its ACL manager(s)), and are in general beyond the scope of this document. As such, the specifications of required rights in this chapter are to be interpreted as suggestions only, whose exact interpretation must be specified by the implementing servers. To emphasise this, the permissions mentioned in the required rights of this chapter are given hypothetical "names", explicitly denoted with quotation marks (indicating that their exact interpretation is to be specified by the specific server in question). Typical interpretations of these hypothetical permissions are given as suggestions.

For an explicit example of a concrete interpretation, namely in the specific case of the RS server (whose specification is within the scope of this document), see RS Protected Objects and their ACL Manager Types .

rdacl_lookup()

The rdacl_lookup() operation retrieves ("reads") all ACLs specified by an <rpc_handle, component_name, manager_type, acl_type> 4-tuple, creating a copy locally on the client.

void rdacl_lookup ( [in] handle_t rpc_handle, [in] sec_acl_component_name_t component_name, [in] uuid_t *manager_type, [in] sec_acl_type_t acl_type, [out] sec_acl_result_t *acl_result );

The rpc_handle parameter identifies the server that manages the protected object.

The component_name parameter further identifies the protected object within the server.

The manager_type parameter identifies an ACL manager type UUID.

The acl_type parameter identifies an ACL type.

The acl_result parameter returns the result of the operation.

Required rights (suggested): This operation succeeds only if the calling client has "rdacl-lookup" permission (to the specified protected object, according to the specified ACL manager's policy-see Implementation Variability Regarding Required Rights ). Typically, servers will grant this permission to clients which have Read-ACL permission to the protected object in question (which, in turn, is typically interpreted as any access-see ACL Managers, Permissions, Access Determination Algorithms ).

rdacl_replace()

The rdacl_replace() operation applies ("writes") all ACLs specified by an <rpc_handle, component_name, manager_type, acl_type> 4-tuple. This operation is atomic, in the sense that it manipulates a whole ACL (not its individual ACLEs, and it cannot be "interrupted" by another invocation of rdacl_replace()) -thus, the specified new ACL entirely replaces the old (existing) ACL on the protected object.

void rdacl_replace ( [in] handle_t rpc_handle, [in] sec_acl_component_name_t component_name, [in] uuid_t *manager_type, [in] sec_acl_type_t acl_type, [in] sec_acl_list_t *acl_list, [out] error_status_t *status );

The rpc_handle parameter identifies the server that manages the protected object.

The component_name parameter further identifies the protected object within the server.

The manager_type parameter identifies an ACL manager type UUID.

The acl_type parameter identifies an ACL type.

The acl_list parameter specifies the new ACLs to replace the old ACLs.

The status parameter returns the status of the operation.

Required rights (suggested): This operation succeeds only if the calling client has "rdacl-replace" permission (to the specified protected object, according to the specified ACL manager's policy-see Implementation Variability Regarding Required Rights ). Typically, servers will grant this permission to clients which have Control (Write-ACL) permission to the protected object in question (see ACL Managers, Permissions, Access Determination Algorithms ).

rdacl_get_access()

The rdacl_get_access() operation determines the calling client's access rights to the protected object specified by an <rpc_handle, component_name, manager_type> 3-tuple.

void rdacl_get_access ( [in] handle_t rpc_handle, [in] sec_acl_component_name_t component_name, [in] uuid_t *manager_type, [out] sec_acl_permset_t *access_rights, [out] error_status_t *status );

The rpc_handle parameter identifies the server that manages the protected object.

The component_name parameter further identifies the protected object within the server.

The manager_type parameter identifies an ACL manager type UUID.

The access_rights parameter returns the calling client's access rights to the specified protected object. This is the client's "maximum" access rights; that is, the "union" (bitwise OR) of all the permission bits granted to the client, according to the ACLs on the protected object of ACL type sec_acl_type_object.

The status parameter returns the status of the operation.

Required rights (suggested): This operation succeeds only if the calling client has "rdacl-get-access" permission (to the specified protected object, according to the specified ACL manager's policy-see Implementation Variability Regarding Required Rights ). Typically, servers will grant this permission to clients which have Read-ACL permission to the protected object in question (which, in turn, is typically interpreted as any access-see ACL Managers, Permissions, Access Determination Algorithms ).

rdacl_test_access()

The rdacl_test_access() operation determines ("tests") whether or not the calling client has the specified access rights to a protected object.

boolean32 rdacl_test_access ( [in] handle_t rpc_handle, [in] sec_acl_component_name_t component_name, [in] uuid_t *manager_type, [in] sec_acl_permset_t access_rights, [out] error_status_t *status );

The rpc_handle parameter identifies the server that manages the protected object.

The component_name parameter further identifies the protected object within the server.

The manager_type parameter identifies an ACL manager type UUID of the protected object.

The access_rights parameter identifies the specific access rights (according to the ACLs on the protected object of ACL type sec_acl_type_object) to be tested.

The status parameter returns the status of the operation.

The boolean32 return value of this operation, which is valid only when status returns error_status_ok, returns 0 ("false") if the calling client is denied access, non-0 ("true") if the client is granted access.

Required rights (suggested): This operation succeeds only if the calling client has "rdacl-test-access" permission (to the specified protected object, according to the specified ACL manager's policy-see Implementation Variability Regarding Required Rights ). Typically, servers will grant this permission to all clients (that is, no permissions are required).

rdacl_place_holder_1()

The rdacl_place_holder_1() operation is merely an IDL place-holder; it is a "no-op" (that is, the specification of its semantics is empty). (The presence of this operation is anachronistic, but necessary.)

boolean32 rdacl_place_holder_1 ( [in] handle_t rpc_handle, [in] sec_acl_component_name_t _1_, [in] uuid_t *_2_, [in, ptr] sec_id_pac_t *_3_, [in] sec_acl_permset_t _4_, [out] error_status_t *status );

The rpc_handle parameter identifies the server that manages the protected object.

The _1_ parameter has unspecified semantics.

The _2_ parameter has unspecified semantics.

The _3_ parameter has unspecified semantics.

The _4_ parameter has unspecified semantics.

The status parameter returns the status of the operation. It always returns sec_acl_not_implemented.

The boolean32 return value of this operation always returns 0 ("false").

Required rights (suggested): None.

rdacl_get_manager_types()

The rdacl_get_manager_types() operation retrieves the types of ACL managers protecting a protected object.

void rdacl_get_manager_types ( [in] handle_t rpc_handle, [in] sec_acl_component_name_t component_name, [in] sec_acl_type_t acl_type, [in] unsigned32 count_max, [out] unsigned32 *count, [out] unsigned32 *num_manager_types, [out, size_is(count_max), length_is(*count)] uuid_t manager_types[], [out] error_status_t *status );

The rpc_handle parameter identifies the server that manages the protected object.

The component_name parameter further identifies the protected object within the server.

The acl_type parameter identifies an ACL type.

The count_max parameter identifies the maximum number of ACL manager type UUIDs to be returned (in manager_types).

The count parameter identifies the actual number of ACL manager type UUIDs returned (in manager_types).

The num_manager_types parameter identifies the total number of ACL manager types, of ACL type acl_type, at the heads of chains (see rdacl_get_printstring(), rdacl_get_printstring() ), protecting the protected object-thus, an invocation of this operation is "completely successful" only if count = num_manager_types.

The manager_types parameter is an array (of size count) of distinct UUIDs identifying different ACL manager types protecting the protected object (in the case of a chain of ACL managers, each supporting <= 32 permission bits, only the first ACL manager in the chain is returned in this way, and the rest are returned by calls to rdacl_get_printstring() -see rdacl_get_printstring() ).

The status parameter returns the status of the operation.

Required rights (suggested): This operation succeeds only if the calling client has "rdacl-get-manager-types" permission (to the specified protected object, according to the specified server's policy (which may, in turn, depend on the policies of the protected object's ACL managers)-see Implementation Variability Regarding Required Rights ). Typically, servers will grant this permission to all clients (that is, no permissions are required).

rdacl_get_printstring()

The rdacl_get_printstring() operation retrieves printstring representations for the permission bits that an ACL manager supports.

void rdacl_get_printstring ( [in] handle_t rpc_handle, [in] uuid_t *manager_type, [in] unsigned32 count_max, [out] uuid_t *manager_type_next, [out] sec_acl_printstring_t *manager_info, [out] boolean32 *tokenize, [out] unsigned32 *num_printstrings, [out] unsigned32 *count, [out, size_is(count_max), length_is(*count)] sec_acl_printstring_t printstrings[], [out] error_status_t *status );

The rpc_handle parameter identifies the server that manages the ACL manager.

The manager_type parameter identifies an ACL manager type UUID.

The count_max parameter identifies the maximum number of printstrings to be returned (in printstrings).

The manager_type_next parameter, if not equal to uuid_nil, identifies the next ACL manager type in a linked list or "chain" of ACL manager types, which can be successively followed until the chain is exhausted (for example, such a chain can be used to support > 32 permission bits). The value uuid_nil indicates the end of this chain.

The manager_info parameter provides a name and help information for the manager_type ACL manager as a whole (as opposed to any of its specific permission bits-those are described in the printstrings parameter), as well as a complete list of all its supported permission bits (represented as the union (bitwise OR) of all those supported bits). Concerning this bitwise OR, it is suggested that, by convention, "simple" or "primitive" permission bits (for example, permissions having semantics not interpretable in terms of other permissions) appear in low-order bit positions (and in particular, that the 7 common permission bits, if present, occupy their usual places in the low-order 7 bit positions, 0x0000007f-see Common Permissions ), and that "complex" or "combination" permission bits (for example, permissions having semantics interpretable in terms of other permissions) appear near the high-order end. Thus, for example, for an ACL manager supporting the first 6 of the 7 common permission bits (rwxcid but not t) plus 2 combination bits, one with value 0x00000080 and having the semantics "Read and Write", and the other with value 0x00000100 and having the semantics "Read or Write", this bitwise OR would be equal to 0x000001bf.

Note:
This example, using "combined rights", is contrived to illustrate the problem of tokenisation (below)-it is not necessarily a realistic example. Combining rights in this manner is not necessarily to be encouraged, and the merits/demerits of doing so are not debated here.)

The tokenize parameter identifies potential ambiguity in the concatenation of permission printstrings (that is, in the printstring fields of the elements of the printstrings[] array)-when tokenize is 0 ("false"), the permission printstrings may be concatenated into a single string without ambiguity; when non-0 ("true"), this property does not hold, and the permission printstrings must be "tokenised" (that is, separated by disambiguating characters; for example, by non-alphanumeric characters, such as whitespace) to avoid ambiguity when concatenated. The consumer of the tokenize parameter is typically a user interface program (for example, an ACL editor) which wants to display printstrings to users, and must do so unambiguously. Thus in the example above, if the two combination permissions were represented by, say, the printstrings raw (for "Read and Write") and row (for "Read or Write"), then tokenize would be non-0 (because these printstrings have characters in common with one another, as well as with the common printstrings r ("Read") and w ("Write"), and this could potentially be confusing to human users). In this example, a user interface program could display the 8 supported permissions to humans in a manner such as: r*w*x*c*i*d*raw*row, where "*" denotes the space character (for visual clarity). Alternatively (and probably preferably), tokenisation could have been avoided in this example by choosing different printstrings for the combination permissions, such as a and o instead of raw and row, in which case a user interface program could display the supported permissions as rwxcidao. (Note that the order of display of permission bits need not be correlated to the order of their values-that's an implementation decision of the user interface program itself, though the reverse-value order indicated here is suggested, for consistency with the well-known 7 common permissions, rwxcidt.)

The num_printstrings parameter identifies the total number (<= 32) of permission bits and printstrings "supported" (in the sense of rdacl_get_printstring(), as indicated in the following sentence) by the ACL manager (thus, an invocation of this operation is "completely successful" only if count = num_printstrings). In the example above, the value of num_printstrings is 9, even though only 8 permission bits are "actually supported" by the manager_type ACL manager (the t bit is not supported, but its position is reserved by convention, so must be skipped).

The count parameter identifies the actual number of printstrings returned (in the printstrings array). In the example above, the value of count is 9.

The printstrings parameter is an array (of size count) of printstrings returning information about the permission bits (see manager_info above) supported by the ACL manager. (See Printstrings and Helpstrings .) The correspondence between supported permission bits and information about those bits is realised "as if" it were given by an array of permission bit / printstring pairs (unsupported permission bits corresponding to NULL printstrings). That is, if permission bit 2k (0 <= k <= 31) is supported (this bit is set in the perm field of manager_info-see Printstrings and Helpstrings ), then printstring[k] contains the information about this permission bit. Unsupported permissions correspond to NULL printstrings. Thus in the example above, printstring[6] is NULL because it corresponds to the unsupported permission bit t.

The status parameter returns the status of the operation.

Required rights (suggested): This operation succeeds only if the calling client has "rdacl-get-printstring" permission (to the specified ACL manager, according to the specified ACL manager's policy-see Implementation Variability Regarding Required Rights ). Typically, servers will grant this permission to all clients (that is, no permissions are required).

rdacl_get_referral()

The rdacl_get_referral() operation supports a server replication strategy wherein ACL "updates" (.Fn rdacl_replace ) may not be supported at all "sites" (that is, by all server instances or replicas). This operation, which refers clients to sites where ACLs can be updated, is to be invoked by a client after an update operation targeted to an ACL site yields a sec_acl_site_read_only status error != error_status_ok. (Non-replicated servers never return a sec_acl_site_read_only status value, so they can provide a trivial implementation of this operation; for example, by returning sec_acl_not_implemented as the status parameter.)

void rdacl_get_referral ( [in] handle_t rpc_handle, [in] sec_acl_component_name_t component_name, [in] uuid_t *manager_type, [in] sec_acl_type_t acl_type, [out] sec_acl_tower_set_t *tower_set, [out] error_status_t *status );

The rpc_handle parameter identifies the server that manages the ACLs in question.

The component_name parameter further identifies a protected object within the server.

The manager_type parameter identifies an ACLE manager type UUID.

The acl_type parameter identifies an ACL type.

The tower_set parameter identifies the actual update referral information itself (represented as RPC towers, to which the client can rebind).

The status parameter returns the status of the operation.

Required rights (suggested): This operation succeeds only if the calling client has "rdacl-get-referral" permission (to the specified server, according to the server's policy-see Implementation Variability Regarding Required Rights ). Typically, servers will grant this permission to all clients (that is, no permissions are required).

rdacl_get_mgr_types_semantics()

The rdacl_get_mgr_types_semantics() operation determines the types of ACL managers protecting a protected object, and the extent of their conformance to POSIX semantics.

void rdacl_get_mgr_types_semantics ( [in] handle_t rpc_handle, [in] sec_acl_component_name_t component_name, [in] sec_acl_type_t acl_type, [in] unsigned32 count_max, [out] unsigned32 *count, [out] unsigned32 *num_manager_types, [out, size_is(count_max), length_is(*count)] uuid_t manager_types[], [out, size_is(count_max), length_is(*count)] sec_acl_posix_semantics_t posix_semantics[], [out] error_status_t *status ); } /* end running listing of rdacl interface */

The description of rdacl_get_mgr_types_semantics() is identical to that of rdacl_get_manager_types(), except that it returns the additional posix_semantics array parameter.

The posix_semantics parameter is an array of flag words indicating the semantics that the corresponding ACL manager in the manager_types array supports.

Required rights (suggested): This operation succeeds only if the calling client has "rdacl-get-mgr-types-semantics" permission (to the specified protected object, according to the specified server's policy-which may, in turn, depend on the policies of the protected object's ACL managers-see Implementation Variability Regarding Required Rights ).

Typically, servers will grant this permission to all clients (that is, no permissions are required).

Please note that the html version of this specification may contain formatting aberrations. The definitive version is available as an electronic publication on CD-ROM from The Open Group.

Contents Next section Index