PreviousNext

The acl2.c Code

The following code is a listing of the acl2.c program:

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

* *

* COPYRIGHT (C) SIEMENS NIXDORF INFORMATIONSSYSTEME AG 1991 *

* ALL RIGHTS RESERVED *

* *

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


/*

* This sample program displays the access permissions (ACL) on each

* entry in the directory for a specific user. The permissions are

* presented in a form similar to the UNIX file permissions. In

* addition, each entry is flagged as either a master or a shadow copy.

*

* The distinguished name of the user performing the check is:

*

* /C=de/O=sni/OU=ap/CN=norbert

*

* The results are presented in the following format:

*

* [ABCD] <entry's distinguished name>

*

* A: 'm' master copy

* 's' shadow copy

*

* B: 'r' read access to public attributes

* 'w' write access to public attributes

* '-' no access to public attributes

*

* C: 'r' read access to standard attributes

* 'w' write access to standard attributes

* '-' no access to standard attributes

*

* D: 'r' read access to sensitive attributes

* 'w' write access to sensitive attributes

* '-' no access to sensitive attributes

*

* For example, the following result means that the entry

* '/C=de/O=sni' is a master copy and that the requesting user

* (/C=de/O=sni/OU=ap/CN=norbert) has write access to its public

* attributes, read access to its standard attributes and no access

* to its sensitive attributes.

*

* [mwr-] /C=de/O=sni

*

* The program requires that the specific user perform an authenticated

* bind to the directory. In order to achieve this the user's

* credentials must already exist in the directory. Therefore the

* following tree of 6 entries is added to the directory each time the

* program runs, and removed again afterwards.

*

* O C=de

* | (objectClass=Country,

* | ACL=(mod-pub: *

* | read-std:*

* | mod-std: *

* | read-sen:*

* | mod-sen: *))

* |

* |

* O O=sni

* | (objectClass=Organization,

* | ACL=(mod-pub: /C=de/O=sni/OU=ap/*

* | read-std:/C=de/O=sni/OU=ap/CN=stefanie

* | mod-std: /C=de/O=sni/OU=ap/CN=stefanie

* | read-sen:/C=de/O=sni/OU=ap/CN=stefanie

* | mod-sen: /C=de/O=sni/OU=ap/CN=stefanie))

* |

* O OU=ap

* | (objectClass=OrganizationalUnit,

* | ACL=(mod-pub: /C=de/O=sni/OU=ap/*

* | read-std:/C=de/O=sni/OU=ap/CN=stefanie

* | mod-std: /C=de/O=sni/OU=ap/CN=stefanie

* | read-sen:/C=de/O=sni/OU=ap/CN=stefanie

* | mod-sen: /C=de/O=sni/OU=ap/CN=stefanie))

* |

* +-------+-------+

* | | |

* | | O CN=ingrid

* | | (objectClass=OrganizationalPerson,

* | | ACL=(mod-pub: /C=de/O=sni/OU=ap/*

* | | read-std:/C=de/O=sni/OU=ap/*

* | | mod-std: /C=de/O=sni/OU=ap/CN=stefanie

* | | read-sen:/C=de/O=sni/OU=ap/*

* | | mod-sen: /C=de/O=sni/OU=ap/CN=stefanie),

* | | surname="Schmid",

* | | telephone="+49 89 636 0",

* | | userPassword="secret")

* | |

* | O CN=norbert

* | (objectClass=OrganizationalPerson,

* | ACL=(mod-pub: /C=de/O=sni/OU=ap/*

* | read-std:/C=de/O=sni/OU=ap/*

* | mod-std: /C=de/O=sni/OU=ap/CN=stefanie

* | read-sen:/C=de/O=sni/OU=ap/*

* | mod-sen: /C=de/O=sni/OU=ap/CN=stefanie),

* | surname="Schmid",

* | telephone="+49 89 636 0",

* | userPassword="secret")

* |

* O CN=stefanie

* (objectClass=OrganizationalPerson,

* ACL=(mod-pub: /C=de/O=sni/OU=ap/*

* read-std:/C=de/O=sni/OU=ap/*

* mod-std: /C=de/O=sni/OU=ap/CN=stefanie

* read-sen:/C=de/O=sni/OU=ap/*

* mod-sen: /C=de/O=sni/OU=ap/CN=stefanie),

* surname="Schmid",

* telephone="+49 89 636 0",

* userPassword="secret")

*

*

* In this version of the program, instead of providing client-generated

* public objects, the XOM Convenience Functions are used for creating

* objects. They are also used for extracting information from service

* generated objects.

*/

#ifdef THREADSAFE

#include <pthread.h>

#endif

#include <stdio.h>

#include <xom.h>

#include <xds.h>

#include <xdsbdcp.h>

#include <xdsgds.h>

#include <xdscds.h>

#include <xdsext.h> /* convenience functions header file */

#include <xomext.h> /* convenience functions header file */

#include "acl2.h"

void

main(

int argc,

char *argv[]

)

{

OM_workspace workspace; /* Workspace for objects */

OM_private_object session; /* Session object. */

OM_private_object bound_session; /* Holds the Session object which */

/* is returned by ds_bind() */

OM_private_object context; /* Context object. */

OM_private_object result; /* Holds the search result object.*/

OM_sint invoke_id; /* Integer for the invoke id */

/* returned by ds_search(). */

/* (this parameter must be present*/

/* even though it is ignored). */

OM_type navigation_path[] = { DS_SEARCH_INFO, 0 };

/* List of OM types to the target */

/* object - of the search result */

OM_type entry_list[] = { DS_ENTRIES, 0 };

/* List of types to be extracted */

OM_public_object entry; /* Entry object from search info. */

OM_value_position total_num; /* Number of descriptors returned.*/

OM_return_code rc; /* XOM function return code. */

register int i;

char user_name[MAX_DN_LEN] = DN_NORBERT;

/* Holds the requestor's name - */

/* "/C=de/O=sni/OU=ap/CN=norbert" */

char entry_string[MAX_DN_LEN + 7] = "[?r??] ";

/* Holds entry details. */

struct entry entry_array[6];/* List of entry names and attrs */

OM_object credentials; /* Credentials part of session obj*/

OM_object use_copy; /* Specifies whether to use shadow*/

/* entries, in context object */

OM_object filter; /* Filter - for search operation */

OM_object dn_root; /* Name object for "/" */

OM_object selection_acl; /* Entry Information */

/* Selection obj */

static char *name_list[] =

{ DN_DE, DN_SNI, DN_AP, DN_STEFANIE,

DN_NORBERT, DN_INGRID };

/* Array of names to be added */

static char *C_attr_list[] = { OBJ_CLASS_C };

static char *O_attr_list[] = { OBJ_CLASS_O, ATT_ACL1 };

static char *OU_attr_list[] = { OBJ_CLASS_OU };

static char *OP_attr_list[] = { OBJ_CLASS_OP, ATT_ACL2,

ATT_SURNAME, ATT_PHONE_NUM, ATT_PASSWORD };

/* Attribute lists, in string fmt */

static char *dn_root_str = DN_ROOT;

static char *filter_str = FILTER;

/* Step 3

*

* Initialize a directory workspace for use by XOM.

*/

if ((workspace = ds_initialize()) == (OM_workspace)0)

printf("ds_initialize() error\n");

/* Step 4

*

* Negotiate the use of the BDC and GDS packages.

*/

if (ds_version(features, workspace) != DS_SUCCESS)

printf("ds_version() error\n");

/* Step 5

*

* Build name objects for entries to be added to the directory.

*/

for (i = 0; i < NO_OF_ENTRIES; i++)

if (! build_name_object(workspace,name_list[i],

&(entry_array[i].name)))

printf("build_name_object() error\n");

/* Step 6

*

* Build attribute objects for entries to be added to the directory

*/

if ((! build_attr_list_object(workspace, NO_C_ATTRS, C_attr_list,

&entry_array[0].attr_list)) ||

(! build_attr_list_object(workspace, NO_O_ATTRS, O_attr_list,

&entry_array[1].attr_list)) ||

(! build_attr_list_object(workspace, NO_OU_ATTRS, OU_attr_list,

&entry_array[2].attr_list)) ||

(! build_attr_list_object(workspace, NO_OP_ATTRS, OP_attr_list,

&entry_array[3].attr_list)))

printf("build_attr_list_object() error\n");

/*

* These entries also have the OP attribute list.

*/

entry_array[4].attr_list = entry_array[3].attr_list;

entry_array[5].attr_list = entry_array[3].attr_list;

/* Step 7

*

* Add a fixed tree of entries to the directory in order to permit

* an authenticated bind by: /C=de/O=sni/OU=ap/CN=norbert

*/

if (! add_tree(workspace, entry_array, NO_OF_ENTRIES))

printf("add_tree() error\n");

/* Step 8

*

* Create a default session object.

*/

if ((rc = om_create(DSX_C_GDS_SESSION,OM_TRUE,workspace,&session))

!= OM_SUCCESS)

printf("om_create() error %d\n", rc);

/* Step 9

*

* Build an object with the following credentials:

* requestor: /C=de/O=sni/OU=ap/CN=norbert

* password: "secret"

* authentication mechanism: simple

*/

if (! build_credentials_object(entry_array[4].name,&credentials))

printf("build_credentials_object() error\n");

/*

* Alter the default session object to include the credentials

*/

if ((rc = om_put(session, OM_REPLACE_ALL, credentials, 0 ,0, 0))

!= OM_SUCCESS)

printf("om_put() error %d\n", rc);

/* Step 10

*

* Bind with credentials to the default GDS server. The

* returned session object is stored in the private object variable

* bound_session and is used for all further XDS function calls.

*/

if (ds_bind(session, workspace, &bound_session) != DS_SUCCESS)

printf("ds_bind() error\n");

/* Step 11

*

* Create a default context object.

*/

if ((rc = om_create(DSX_C_GDS_CONTEXT,OM_TRUE,workspace,&context))

!= OM_SUCCESS)

printf("om_create() error %d\n", rc);

/*

* Build an object specifying that shadow entries should be used.

*/

if (! build_use_copy_object(&use_copy))

printf("build_use_copy_object() error\n");

/*

* Alter the default context object to include 'shadow' entries.

*/

if ((rc = om_put(context, OM_REPLACE_ALL, use_copy, 0 ,0, 0))

!= OM_SUCCESS) printf("om_put() error %d\n", rc);

/* Step 12

*

* Build a filter object, specifying presence of object class attr.

*/

if (! build_filter_object(workspace, filter_str, &filter))

printf("build_filter_object() error\n");

/*

* Build a root name object, name = "/"

*/

if (! build_name_object(workspace, dn_root_str, &dn_root))

printf("build_name_object() error\n");

/*

* Build an entry information selection object,

* selecting acl attributes.

*/

if (! build_selection_object(&selection_acl))

printf("build_selection_object() error\n");

/* Step 13

*

* Search the whole subtree below root. The filter selects entries

* with an object-class attribute. The selection extracts the ACL

* attribute from each selected entry. The results are returned in

* the private object 'result'.

*

* NOTE: Since every entry contains an object-class attribute the

* filter performs no function other than to demonstrate how

* filters may be used.

*/

if (ds_search(bound_session, context, dn_root, DS_WHOLE_SUBTREE, filter,

OM_FALSE, selection_acl, &result, &invoke_id) != DS_SUCCESS)

printf("ds_search() error\n");

/* Step 14

*

* Close the connection to the GDS server.

*/

if (ds_unbind(bound_session) != DS_SUCCESS)

printf("ds_unbind() error\n");

/* Step 15

*

* Remove the user's credentials from the directory.

*/

if (! remove_tree(workspace, session, entry_array, NO_OF_ENTRIES))

printf("remove_tree() error\n");

/* Step 16

*

* Free the name and attribute objects

* which make up the directory entries.

*/

if (! free_entry_list(entry_array))

printf("free_entry_list() error\n");

/*

* Free public objects which were created.

*/

free(selection_acl);

free(use_copy);

free(credentials);

if ((om_delete(filter) != OM_SUCCESS) ||

(om_delete(dn_root) != OM_SUCCESS))

printf("om_delete() error\n");

/* Step 17

*

* Extract components from the search result by means of the XOM

* Convenience Function, omX_extract()

*/

if ((rc = omX_extract(result, navigation_path,

OM_EXCLUDE_ALL_BUT_THESE_TYPES + OM_EXCLUDE_SUBOBJECTS,

entry_list, OM_FALSE, 0, 0, &entry, &total_num))

!= OM_SUCCESS)

printf("omX_extract(Search-Result) error %d\n", rc);

/*

* Requestor's name = "/C=de/O=sni/OU=ap/CN=norbert"

*/

printf("User: %s\nTotal: %d\n", user_name, total_num);

/* Step 18

*

* Examine each entry and print the entry details.

*/

for (i = 0; i < total_num; i++) {

if (process_entry_info((entry+i)->value.object.object,

entry_string, user_name))

printf("%s\n", entry_string);

}

/*

* Now free the entry object (returned from omX_extract() ).

*/

if (om_delete(entry) != OM_SUCCESS)

printf("om_delete() error\n");

/* Step 19

*

* Close the directory workspace.

*/

if (ds_shutdown(workspace) != DS_SUCCESS)

printf("ds_shutdown() error\n");

}

/*

* Add the tree of entries described above.

*/

int

add_tree(

OM_workspace workspace,

struct entry elist[],

int no_entries

)

{

OM_private_object session; /* Holds the Session object which */

/* is returned by ds_bind() */

OM_sint invoke_id; /* Integer for the invoke id */

int error = 0;

int i;

/*

* Bind (without credentials) to the default GDS server.

*/

if (ds_bind(DS_DEFAULT_SESSION, workspace, &session) != DS_SUCCESS)

error++;

/*

* Add entries to the GDS server.

*/

for (i = 0; i < no_entries; i++)

if (ds_add_entry(session, DS_DEFAULT_CONTEXT, elist[i].name,

elist[i].attr_list, &invoke_id) != DS_SUCCESS) {

/* Ignore error if adding country - possibly already there */

if (i != 0) error++;

}

/*

* Close the connection to the GDS server.

*/

if (ds_unbind(session) != DS_SUCCESS)

error++;

return (error?0:1);

}

/*

* Remove the tree of entries described above.

*/

int

remove_tree(

OM_workspace workspace,

OM_private_object session,

struct entry elist[],

int no_entries

)

{

OM_private_object bound_session; /* Holds the Session object which */

/* is returned by ds_bind() */

OM_sint invoke_id; /* Integer for the invoke id */

int i;

int error = 0;

/*

* Bind (without credentials) to the default GDS server.

*/

if (ds_bind(session, workspace, &bound_session) != DS_SUCCESS)

error++;

/*

* Remove entries from the GDS server.

*/

for (i = no_entries-1; i >= 0; i--)

if (ds_remove_entry(bound_session, DS_DEFAULT_CONTEXT,

elist[i].name, &invoke_id) != DS_SUCCESS) {

/* Ignore error if removing country - possibly has entries */

/* below it */

if (i != 0) error++;

}

/*

* Close the connection to the GDS server.

*/

if (ds_unbind(bound_session) != DS_SUCCESS)

error++;

return (error?0:1);

}

/*

* Extract information about an entry from the Entry-Info object: whether

* the entry is a master-copy, its ACL permissions and its distinguished

* name. Build up a string based on this information.

*/

int

process_entry_info(

OM_private_object entry,

char *entry_string,

char *user_name

)

{

OM_return_code rc; /* Return code from XOM function. */

OM_public_object ei_attrs; /* Components from Entry-Info. */

OM_public_object attr; /* Directory attribute. */

OM_public_object acl; /* ACL attribute parts. */

OM_public_object acl_vals; /* ACL attribute value. */

OM_public_object acl_item; /* ACL item component. */

OM_value_position total_attrs; /* Number of attributes returned. */

OM_value_position total_acls; /* Number of acl values returned. */

register int i;

register int interp;

register int error = 0;

register int found_acl = 0;

static OM_type ei_attr_list[] = { DS_FROM_ENTRY,

DS_OBJECT_NAME,

0 };

/* Attributes to be extracted. */

OM_string entry_str;

/*

* Extract occurences of DS_FROM_ENTRY, and DS_OBJECT_NAME

* from each Entry-Info object.

*/

if ((rc = om_get(entry, OM_EXCLUDE_ALL_BUT_THESE_TYPES,

ei_attr_list, OM_FALSE, 0, 0, &ei_attrs, &total_attrs))

!= OM_SUCCESS) {

error++;

printf("om_get(Entry-Info) error %d\n", rc);

}

for (i = 0; ((i < total_attrs) && (! error)); i++, ei_attrs++) {

/*

* Determine if current entry is a master-copy or a shadow-copy.

*/

if ((ei_attrs->type == DS_FROM_ENTRY) &&

((ei_attrs->syntax & OM_S_SYNTAX) == OM_S_BOOLEAN))

if (ei_attrs->value.boolean == OM_TRUE)

entry_string[1] = 'm';

else if (ei_attrs->value.boolean == OM_FALSE)

entry_string[1] = 's';

else

entry_string[1] = '?';

/*

* Convert the entry's distinguished name to a string format.

*/

entry_str.elements = &entry_string[7];

entry_str.length = MAX_DN_LEN;

if ((ei_attrs->type == DS_OBJECT_NAME) &&

((ei_attrs->syntax & OM_S_SYNTAX) == OM_S_OBJECT))

if ((rc = omX_object_to_string(ei_attrs->value.object.object,

OM_FALSE, &entry_str)) != OM_SUCCESS) {

error++;

printf("omX_object_to_string() error\n");

}

}

/*

* Now extract occurences of attributes, where the attribute

* type is ACL from the Entry-Info object.

*/

dsX_extract_attr_values(entry, DSX_A_ACL, OM_TRUE,

&acl_vals, &total_acls);

for (i = 0; ((i < total_acls) && (! error)); i++) {

acl = acl_vals[i].value.object.object;

/*

* Examine the ACL. Check each permission for the current user.

*/

entry_string[2] = 'r';

entry_string[3] = '-';

entry_string[4] = '-';

while (acl->type != OM_NO_MORE_TYPES) {

if ((acl->syntax & OM_S_SYNTAX) == OM_S_OBJECT)

acl_item = acl->value.object.object;

switch (acl->type) {

case OM_CLASS:

break;

case DSX_MODIFY_PUBLIC:

if (permitted_access(user_name, acl_item))

entry_string[2] = 'w';

break;

case DSX_READ_STANDARD:

if (permitted_access(user_name, acl_item))

entry_string[3] = 'r';

break;

case DSX_MODIFY_STANDARD:

if (permitted_access(user_name, acl_item))

entry_string[3] = 'w';

break;

case DSX_READ_SENSITIVE:

if (permitted_access(user_name, acl_item))

entry_string[4] = 'r';

break;

case DSX_MODIFY_SENSITIVE:

if (permitted_access(user_name, acl_item))

entry_string[4] = 'w';

break;

}

acl++;

}

}

/*

* Now free acl_vals.

*/

if (total_acls > 0)

if ((rc = om_delete(acl_vals)) != OM_SUCCESS) {

error++;

printf("om_delete() error, rc = %d\n", rc);

}

return (error?0:1);

}

/*

* Check if a user is permitted access based on the ACL supplied.

*/

int

permitted_access(

char *user_name,

OM_public_object acl_item

)

{

char acl_name[MAX_DN_LEN];

OM_string acl_name_str;

int interpretation;

int acl_present = 0;

int access = 0;

int acl_name_length;

OM_return_code rc;

while (acl_item->type != OM_NO_MORE_TYPES) {

switch (acl_item->type) {

case OM_CLASS:

break;

case DSX_INTERPRETATION:

interpretation = acl_item->value.boolean;

break;

case DSX_USER:

acl_name_str.elements = acl_name;

if ((rc = omX_object_to_string(acl_item->value.object.object,

OM_FALSE, &acl_name_str)) == OM_SUCCESS) {

if (interpretation == DSX_SINGLE_OBJECT) {

if (strcmp(acl_name, user_name) == 0)

access = 1;

}

else if (interpretation == DSX_ROOT_OF_SUBTREE) {

if ((acl_name_length = strlen(acl_name)) == 0)

access = 1;

else if (strncmp(acl_name,user_name,acl_name_length)

== 0)

access = 1;

}

}

break;

}

acl_item++;

}

return (access);

}

/*

* Build a name object from a name string using the XOM

* Convenience Function omX_string_to_object().

*/

int

build_name_object(

OM_workspace workspace,

char *name,

OM_private_object *name_obj

)

{

OM_integer err_pos;

OM_integer err_type;

OM_return_code rc;

OM_string name_str;

int error = 0;

name_str.length = strlen(name);

name_str.elements = name;

if ((rc = omX_string_to_object(workspace, &name_str, DS_C_DS_DN,

OM_TRUE, name_obj, &err_pos, &err_type)) != OM_SUCCESS)

error++;

return (error?0:1);

}

/*

* Build an attribute list object given a list of attribute strings.

* Use the XOM Convenience Function omX_string_to_object() to build

* an attribute object from an attribute string, and omX_fill() to

* create the other OM descriptor required.

*/

int

build_attr_list_object(

OM_workspace workspace,

OM_integer no_attrs,

char *attr_str_array[],

OM_object *attr_list_obj

)

{

OM_integer err_pos;

OM_integer err_type;

OM_object attr;

OM_object alist;

OM_string attr_str;

OM_return_code rc;

OM_descriptor null_desc = OM_NULL_DESCRIPTOR;

int error = 0;

int i;

/*

* Allocate space for class descriptor, null descriptor and

* one descriptor for each attribute.

*/

if ((alist =

(OM_descriptor *)malloc((2+no_attrs) * sizeof(OM_descriptor)))

== 0)

error++;

if ((rc = omX_fill_oid(OM_CLASS, DS_C_ATTRIBUTE_LIST, &alist[0]))

!= OM_SUCCESS)

error++;

for (i = 1; i <= no_attrs; i++) {

attr_str.length = strlen(attr_str_array[i-1]);

attr_str.elements = attr_str_array[i-1];

if ((rc = omX_string_to_object(workspace, &attr_str, DS_C_ATTRIBUTE,

OM_TRUE, &attr, &err_pos, &err_type)) != OM_SUCCESS)

error++;

if ((rc = omX_fill(DS_ATTRIBUTES, OM_S_OBJECT, 0, attr, &alist[i]))

!= OM_SUCCESS)

error++;

}

alist[i] = null_desc;

*attr_list_obj = alist;

return (error?0:1);

}

/*

* Build an entry info selection object using the XOM Convenience

* Functions omX_fill() and omX_fill_oid() to fill the OM descriptors.

*/

int

build_selection_object(

OM_object *selection_obj

)

{

OM_integer err_pos;

OM_integer err_type;

OM_object desc;

OM_object sel;

OM_return_code rc;

OM_descriptor null_desc = OM_NULL_DESCRIPTOR;

int error = 0;

/*

* Allocate space for class descriptor, null descriptor and one

* descriptor for each attribute.

*/

if ((sel = (OM_descriptor *)malloc((5) * sizeof(OM_descriptor))) == 0)

error++;

if ((rc = omX_fill_oid(OM_CLASS, DS_C_ENTRY_INFO_SELECTION, &sel[0]))

!= OM_SUCCESS)

error++;

if ((rc = omX_fill(DS_ALL_ATTRIBUTES, OM_S_BOOLEAN, OM_FALSE, 0,

&sel[1])) != OM_SUCCESS)

error++;

if ((rc = omX_fill_oid(DS_ATTRIBUTES_SELECTED, DSX_A_ACL,

&sel[2])) != OM_SUCCESS)

error++;

if ((rc = omX_fill(DS_INFO_TYPE, OM_S_ENUMERATION, DS_TYPES_AND_VALUES,

0, &sel[3])) != OM_SUCCESS)

error++;

sel[4] = null_desc;

*selection_obj = sel;

return (error?0:1);

}

/*

* Build a credentials object using the XOM Convenience Function

* omX_fill().

*/

int

build_credentials_object(

OM_object name,

OM_object *credentials_obj

)

{

OM_integer err_pos;

OM_integer err_type;

OM_object cred;

OM_return_code rc;

OM_descriptor null_desc = OM_NULL_DESCRIPTOR;

int error = 0;

/*

* Just allocate space for a null descriptor and two other descriptors,

* no class descriptor required.

*/

if ((cred = (OM_descriptor *)malloc((4) * sizeof(OM_descriptor))) == 0)

error++;

if ((rc = omX_fill(DS_REQUESTOR, OM_S_OBJECT, 0, name, &cred[0]))

!= OM_SUCCESS)

error++;

if ((rc = omX_fill(DSX_PASSWORD, OM_S_OCTET_STRING, (sizeof(PASSWD)-1),

PASSWD, &cred[1])) != OM_SUCCESS)

if ((rc = omX_fill(DSX_AUTH_MECHANISM, OM_S_ENUMERATION, DSX_SIMPLE,

0, &cred[2])) != OM_SUCCESS)

error++;

cred[3] = null_desc;

*credentials_obj = cred;

return (error?0:1);

}

/*

* Build an object setting DS_DONT_USE_COPY to FALSE, using the

* XOM Convenience Function omX_fill().

*/

int

build_use_copy_object(

OM_object *use_copy_obj

)

{

OM_integer err_pos;

OM_integer err_type;

OM_object desc;

OM_object copy;

OM_return_code rc;

OM_descriptor null_desc = OM_NULL_DESCRIPTOR;

int error = 0;

/*

* Just allocate space for a null descriptor and one other

* descriptor, no class descriptor required.

*/

if ((copy = (OM_descriptor *)malloc((2) * sizeof(OM_descriptor))) == 0)

error++;

if ((rc = omX_fill(DS_DONT_USE_COPY, OM_S_BOOLEAN, OM_FALSE, 0,

©[0])) != OM_SUCCESS)

error++;

copy[1] = null_desc;

*use_copy_obj = copy;

return (error?0:1);

}

/*

* Build a filter object from a filter string using the XOM Convenience

* Function omX_string_to_object().

*/

int

build_filter_object(

OM_workspace workspace,

char *filter,

OM_object *filter_obj

)

{

OM_integer err_pos;

OM_integer err_type;

OM_string filter_str;

OM_return_code rc;

int error = 0;

filter_str.length = strlen(filter);

filter_str.elements = filter;

if ((rc = omX_string_to_object(workspace, &filter_str, DS_C_FILTER,

OM_TRUE, filter_obj, &err_pos, &err_type)) != OM_SUCCESS)

error++;

return (error?0:1);

}

/*

* Free the name and attribute list objects in the entry list. Objects

* which have been created using the XOM Convenience Function

* omX_string_to_object() must be deleted using om_delete().

*/

int

free_entry_list(

struct entry entry_array[]

)

{

OM_object attr_list_obj;

int i, j;

int error = 0;

for (i = 0; i < NO_OF_ENTRIES; i++) {

/*

* Delete the service generated public name object .

*/

if (om_delete(entry_array[i].name) != OM_SUCCESS)

error++;

/*

* The last two attribute lists were the same as the 4th one.

*/

if (i < NO_OF_ENTRIES-2) {

attr_list_obj = entry_array[i].attr_list;

for (j = 0; attr_list_obj[j].type != OM_NO_MORE_TYPES; j++) {

if (attr_list_obj[j].type == DS_ATTRIBUTES)

/*

* Delete the service generated public attribute object.

*/

if (om_delete(attr_list_obj[j].value.object.object)

!= OM_SUCCESS)

error++;

}

/*

* Free the whole attribute list object.

*/

free(attr_list_obj);

}

}

return (error?0:1);

}