PreviousNext

The server_acl_mgr_setup Routine

The server_acl_mgr_setup( ) routine performs all the steps necessary to set up ACL databases for the two object types used by the sample application.

/******
*
* server_acl_mgr_setup -- Open and, if necessary, create the ACL-related
* databases, that is:
*
* 1. Set up a default ACL manager for the management interface.
*
* 2. Create an initial ACL. For servers that dynamically create
* objects, this ACL is intended to be used as the ACL on the
* "container" in which objects are created. If the server
* manages static objects, this ACL can be used for some other
* purpose.
*
*
* Called from main().
*
******/

void server_acl_mgr_setup(
unsigned_char_t *db_acl_path, /* Pathname for databases. */
dce_acl_resolve_func_t resolver, /* sample_resolve_by_name. */
uuid_t acl_mgr_uuid, /* ACL manager UUID. */
uuid_t object_uuid, /* Object UUID. */
unsigned_char_t *object_name, /* Object name. */
sec_acl_permset_t owner_perms, /* Owner permission set. */
unsigned_char_t *owner, /* Owner name. */
boolean32 is_container, /* Is this a container object? */
/* == TRUE from main(). */
/* [out] parameters: */
dce_db_handle_t *db_acl, /* ACL-indexed store handle. */
dce_db_handle_t *db_object, /* Object-indexed store handle. */
dce_db_handle_t *db_name, /* Name-indexed store handle. */
uuid_t *object_acl_uuid, /* Object ACL UUID. */
uuid_t *mgmt_acl_uuid, /* Mgmt ACL UUID. */
unsigned32 *status)
{
sec_acl_t new_acl;
uuid_t machine_princ_id;
unsigned_char_t machine_principal[MAXHOSTNAMELEN + 20];
unsigned_char_t *uuid_string;
boolean32 need_init;
unsigned32 dbflags;
static sample_data_t datahdr;
unsigned_char_t *acl_path_string;
sec_acl_permset_t permset = (sec_acl_permset_t) 0;

*status = error_status_ok;
bzero(&datahdr, sizeof datahdr);

uuid_create_nil(object_acl_uuid, status);

need_init = 0;

/* Build the full pathname string for the db_acl database... */
acl_path_string = malloc(MAX_ACL_PATH_SIZE);
strcpy(acl_path_string, db_acl_path);
strcat(acl_path_string, (unsigned_char_t *)"/");
strncat(acl_path_string, "db_acl", strlen("db_acl"));

/* If the thing doesn't exist yet, then we need to do some init- */
/* ialization... */
if (access((char *)acl_path_string, R_OK) != 0)
if (errno == ENOENT)
need_init = 1;

/********************************************************************/

/* Create the indexed-by-UUID databases. There are two of these: */
/* One for the ACL UUID-indexed store, and */
/* One for the Object UUID-indexed store... */

dbflags = db_c_index_by_uuid;
if (need_init)
dbflags |= db_c_create;

/* Open (or create) the "db_acl" ACL UUID-indexed backing store... */
dce_db_open(
(char *)acl_path_string, /* Filename of backing store. */
NULL, /* Backing store "backend type" default == hash. */
dbflags, /* We already specified index by UUID for this. */
(dce_db_convert_func_t)dce_rdacl_convert, /* Serialization */
/* function (generated by IDL). */
db_acl, /* The returned backing store handle. */
status);

/* Set the global variable that records whether we actually have */
/* opened the databases; this enables us to avoid calling the */
/* dce_db_close() routine for unopened databases, which will cause */
/* a core dump... */
databases_open = TRUE;

/* For the object database, we need standard backing store headers */
dbflags |= db_c_std_header;
if (need_init)
dbflags |= db_c_create;

/* Now open (or create) the "db_object" store... */
/* Build the full pathname string for the database... */
free(acl_path_string);
acl_path_string = malloc(MAX_ACL_PATH_SIZE);
strcpy(acl_path_string, db_acl_path);
strcat(acl_path_string, (unsigned_char_t *)"/");
strncat(acl_path_string, "db_object", strlen("db_object"));

dce_db_open(
(char *)acl_path_string, /* Filename of backing store. */
NULL, /* Backing store "backend type" default == hash. */
dbflags, /* Specifies index by UUID, and include standard */
/* headers. */
(dce_db_convert_func_t)sample_data_convert, /* Serialization */
/* function for object data. */
db_object, /* The returned backing store handle. */
status);

/* Create the indexed-by-name database... */
dbflags = db_c_index_by_name;
if (need_init)
dbflags |= db_c_create;

/* Build the full pathname string for the database... */
free(acl_path_string);
acl_path_string = malloc(MAX_ACL_PATH_SIZE);
strcpy(acl_path_string, db_acl_path);
strcat(acl_path_string, (unsigned_char_t *)"/");
strncat(acl_path_string, "db_name", strlen("db_name"));

dce_db_open(
(char *)acl_path_string, /* Filename of backing store. */
NULL, /* Backing store "backend type" default == hash. */
dbflags, /* Specifies index by name. */
(dce_db_convert_func_t)uu_convert, /* Serialization */
/*function for name data. */
db_name, /* The returned backing store handle. */
status);

free(acl_path_string);

/********************************************************************/

/* Now register our ACL manager's object types with the ACL */
/* library... */

/* Register for the mgmt ACL... */
dce_acl_register_object_type(
*db_acl, /* Backing store where ACLs are to be stored. */
&mgmt_acl_mgr_uuid, /* Type of ACL manager: this one is */
/* for mgmt ACL operations; the UUID is defined */
/* globally at the top of this file. */
/* Why do we need this parameter? Well, the way */
/* that the ACL library keeps track of the different */
/* "sets" of ACL databases is by manager UUID. */
/* The manager UUID is what the library will use */
/* to figure out which ACL database to open and */
/* retrieve a requested ACL's contents from. */
/* Essentially what we are doing here is setting */
/* up things so that calls to the library routine */
/* dce_acl_is_client_authorized() can be made to */
/* check our ACLs, giving only the ACL UUID and a */
/* manager UUID to get the desired result. */

sizeof mgmt_printstr/sizeof mgmt_printstr[0], /* Number of */
/* items in mgmt_printstr array. */
mgmt_printstr, /* An array of sec_acl_printstring_t */
/* structures containing the printable */
/* representation of each specified */
/* permission. */
&mgmt_info, /* A single sec_acl_printstring_t containing */
/* the name and short description for */
/* the given ACL manager. */
sec_acl_perm_control, /* Permission set needed to change */
/* an ACL. Constants like these are defined */
/* in <dce/aclbase.h>. */
sec_acl_perm_test, /* Permission set needed to test an ACL. */

resolver, /* Server function to get ACL UUID for a given */
/* object; for us it's the */
/* sample_resolve_by_name() call, below. */
/* This routine is for the use of acl_edit: */
/* it allows acl_edit to receive an object */
/* name and come up with the ACL UUID; at */
/* least that's what I think it's for. */
NULL, /* Argument to pass to resolver function. */
0, /* Flags -- none here. */
status);

/* Now register for the regular ACL... */
dce_acl_register_object_type(
*db_acl, /* Backing store where ACLs are to be stored. */
&sample_acl_mgr_uuid, /* Hard-coded at the top of this */
/* file. */
sizeof sample_printstr/sizeof sample_printstr[0], /* Number */
/* of items in our printstring array. */
sample_printstr, /* An array of sec_acl_printstring_t */
/* structures containing the printable */
/* representation of each specified */
/* permission set. */
&sample_info, /* A single sec_acl_printstring_t containing*/
/* the name and short description for */
/* the manager we're registering. */
sec_acl_perm_control, /* Permission set needed to change an */
/* ACL. */
sec_acl_perm_test, /* The permission you need to test an */
/* ACL maintained by this manager. */

resolver, /* Application server function that gives */
/* the ACL UUID for a given object, when */
/* presented with that object's name; for */
/* us it's the sample_resolve_by_name() */
/* routine, below. */
NULL, /* Argument to pass to resolver routine; */
/* identified as the "resolver_arg" in the */
/* code to that function below. */
0, /* Flags -- none here. */
status);

/* If we're initializing, then we have to create all this stuff... */
if (need_init)
{

dce_svc_printf(NO_ACL_DBS_MSG);
/* Create the mgmt interface ACL... */
server_create_acl(
mgmt_acl_mgr_uuid, /* Create mgmt manager type ACL. */
ALL_MGMT_PERMS, /* Permission set for new ACL. */
owner, /* Principal name for new entry. */
&new_acl, /* This will contain the new ACL. */
mgmt_acl_uuid, /* This will contain the ACL UUID. */
status);

/************************************************************/
/* For the management ACL we must add a default entry for */
/* the machine principal so dced can manage the server. */

/* Construct the name entry string... */
strcpy(machine_principal, "hosts/");
gethostname((char *)(machine_principal + 6), MAXHOSTNAMELEN + 1);
strcat(machine_principal, "/self");

/* Get the machine principal's UUID... */
server_get_local_principal_id(
machine_principal,
&machine_princ_id,
status);

/* Add a user entry for the machine principal to the new */
/* ACL... */
permset = ALL_MGMT_PERMS;
dce_acl_obj_add_user_entry(
&new_acl,
permset,
&machine_princ_id,
status);

/* By default everybody must be able to get the principal */
/* name. They should be able to ping too. So add an */
/* appropriate unauthenticated permissions entry to the ACL*/
permset = mgmt_perm_inq_pname | mgmt_perm_ping;
dce_acl_obj_add_unauth_entry(
&new_acl,
permset,
status);

/* Add permissions for the any_other entry in the ACL... */
permset = mgmt_perm_inq_pname | mgmt_perm_ping;
dce_acl_obj_add_any_other_entry(
&new_acl,
permset,
status);

/* Store the mgmt ACL... */
server_store_acl(
*db_acl, /* The ACL UUID-indexed store. */
*db_object, /* The object UUID-indexed store. */
*db_name, /* The name ("residual")-indexed store. */
&new_acl, /* The ACL itself. */
mgmt_acl_uuid, /* The mgmt ACL UUID. */
&mgmt_object_uuid, /* The mgmt object UUID. */
(unsigned_char_t *)MGMT_OBJ_NAME, /* The mgmt */
/* object name. */
/* (void*) */ &datahdr, /* The data header = object */
/* contents. */
0, /* Not a container ACL. */
status);

/********************************************************************/
/* Object ACL creation code... */

/* Now create the object ACL... */
server_create_acl(
sample_acl_mgr_uuid, /* Create an ACL with this */
/* manager type. */
owner_perms, /* Give it these permissions. */
owner, /* Make this the principal name. */
&new_acl, /* This will contain new ACL. */
object_acl_uuid, /* This will contain new ACL UUID. */
status);

/* Null the data header... */
bzero(&datahdr, sizeof datahdr);

/* Store the object ACL... */
server_store_acl(
*db_acl, /* The ACL UUID-indexed store. */
*db_object, /* The object UUID-indexed store. */
*db_name, /* The name ("residual")-indexed store. */
&new_acl, /* The ACL itself. */
object_acl_uuid, /* The object ACL UUID. */
&object_uuid, /* The object UUID. */
object_name, /* The object name. */
/* (void*) */ &datahdr, /* The data header = object */
/* contents. */
/* is_container */ 0, /* Is this a container */
/* ACL? */
status);

/* Finally, free the space we were using... */
dce_acl_obj_free_entries(&new_acl, status);

/* ...end of object ACL creation code. */
/********************************************************************/
}
else /* ACL databases already exist; get the two ACL UUIDs... */
{

/* This is a call to sample_resolve_by_name() (see below); */
/* it gives us the UUID of the ACL of the object whose */
/* name we pass it... */
(*resolver)(
NULL, /* No client bind handle; local call. */
object_name, /* Object whose ACL UUID we want. */
0, /* Type of ACL we want UUID of. */
&sample_acl_mgr_uuid, /* Object's manager type. */
0, /* Ignored as far as we're concerned. */
NULL, /* "resolver_arg"; unused. */
object_acl_uuid, /* Will contain object ACL UUID. */
status);

(*resolver)(
NULL, /* No client bind handle; local call. */
(sec_acl_component_name_t)MGMT_OBJ_NAME, /* We want */
/* mgmt object's ACL UUID. */
0, /* Type of ACL we want UUID of. */
&mgmt_acl_mgr_uuid, /* Object's manager type=mgmt. */
0, /* Ignored as far as we're concerned. */
NULL, /* "resolver_arg"; ignored. */
mgmt_acl_uuid, /* Will contain mgmt ACL UUID. */
status);

}

/* Set up remote management authorization to use the ACL manager. */
/* Note that the first parameter to this call is the address of a */
/* management authorization callback routine, which is defined */
/* later in this file... */
rpc_mgmt_set_authorization_fn(sample_mgmt_auth, status);

/* Finally, register the rdacl interface with the runtime... */
rpc_server_register_if(
rdaclif_v1_0_s_ifspec, /* Interface to register. */
NULL, /* Manager type UUID. */
(rpc_mgr_epv_t) &dce_acl_v1_0_epv, /* Entry point */
/* vector. */
status);

}