summaryrefslogtreecommitdiffstats
path: root/lib/libaccess/register.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/libaccess/register.cpp')
-rw-r--r--lib/libaccess/register.cpp821
1 files changed, 821 insertions, 0 deletions
diff --git a/lib/libaccess/register.cpp b/lib/libaccess/register.cpp
new file mode 100644
index 00000000..2973e1d5
--- /dev/null
+++ b/lib/libaccess/register.cpp
@@ -0,0 +1,821 @@
+/** BEGIN COPYRIGHT BLOCK
+ * Copyright 2001 Sun Microsystems, Inc.
+ * Portions copyright 1999, 2001-2003 Netscape Communications Corporation.
+ * All rights reserved.
+ * END COPYRIGHT BLOCK **/
+/*
+ * LAS registration interface
+ */
+
+#include <netsite.h>
+#include <plhash.h>
+#include <base/systems.h>
+#include <base/util.h>
+#include <base/nsassert.h>
+#include "permhash.h"
+#include <libaccess/nserror.h>
+#include <libaccess/acl.h>
+#include "aclpriv.h"
+#include <libaccess/aclproto.h>
+#include <libaccess/aclglobal.h>
+#include <libaccess/ldapacl.h>
+#include "aclcache.h"
+#include <libaccess/dbtlibaccess.h>
+#include <libaccess/aclerror.h>
+
+/* This is to force aclspace.o into ns-httpd30.dll */
+static ACLGlobal_p *link_ACLGlobal = &ACLGlobal;
+
+/* This forces oneeval.o into ns-httpd30.dll */
+static ACLDispatchVector_t **link_nsacl_table = &__nsacl_table;
+
+ACLMethod_t ACLMethodDefault = ACL_METHOD_INVALID;
+ACLDbType_t ACLDbTypeDefault = ACL_DBTYPE_INVALID;
+static char *ACLDatabaseDefault = 0;
+
+ACLDbType_t ACL_DbTypeLdap = ACL_DBTYPE_INVALID;
+
+DbParseFn_t ACLDbParseFnTable[ACL_MAX_DBTYPE];
+
+void
+ACL_LasHashInit()
+{
+ int i;
+
+ ACLLasEvalHash = PR_NewHashTable(0,
+ PR_HashString,
+ PR_CompareStrings,
+ PR_CompareValues,
+ &ACLPermAllocOps,
+ NULL);
+ NS_ASSERT(ACLLasEvalHash);
+
+ ACLLasFlushHash = PR_NewHashTable(0,
+ PR_HashString,
+ PR_CompareStrings,
+ PR_CompareValues,
+ &ACLPermAllocOps,
+ NULL);
+ NS_ASSERT(ACLLasFlushHash);
+
+ ACLMethodHash = PR_NewHashTable(ACL_MAX_METHOD,
+ PR_HashCaseString,
+ PR_CompareCaseStrings,
+ PR_CompareValues,
+ &ACLPermAllocOps,
+ NULL);
+ NS_ASSERT(ACLMethodHash);
+
+ ACLDbTypeHash = PR_NewHashTable(ACL_MAX_DBTYPE,
+ PR_HashCaseString,
+ PR_CompareCaseStrings,
+ PR_CompareValues,
+ &ACLPermAllocOps,
+ NULL);
+ NS_ASSERT(ACLDbTypeHash);
+
+ for (i = 0; i < ACL_MAX_DBTYPE; i++)
+ ACLDbParseFnTable[i] = 0;
+
+ ACLAttrGetterHash = PR_NewHashTable(256,
+ PR_HashCaseString,
+ PR_CompareCaseStrings,
+ PR_CompareValues,
+ &ACLPermAllocOps,
+ NULL);
+ NS_ASSERT(ACLDbTypeHash);
+
+ ACLDbNameHash = PR_NewHashTable(0,
+ PR_HashCaseString,
+ PR_CompareCaseStrings,
+ PR_CompareValues,
+ &ACLPermAllocOps,
+ ACL_DATABASE_POOL);
+ NS_ASSERT(ACLDbNameHash);
+
+ ACLUserLdbHash = PR_NewHashTable(0,
+ PR_HashCaseString,
+ PR_CompareCaseStrings,
+ PR_CompareValues,
+ &ACLPermAllocOps,
+ NULL);
+ NS_ASSERT(ACLUserLdbHash);
+
+ return;
+}
+
+void
+ACL_LasHashDestroy()
+{
+ if (ACLLasEvalHash) {
+ PR_HashTableDestroy(ACLLasEvalHash);
+ ACLLasEvalHash=NULL;
+ }
+ if (ACLLasFlushHash) {
+ PR_HashTableDestroy(ACLLasFlushHash);
+ ACLLasFlushHash=NULL;
+ }
+}
+
+/* ACL_LasRegister
+ * INPUT
+ * errp NSError structure
+ * attr_name E.g. "ip" or "dns" etc.
+ * eval_func E.g. LASIpEval
+ * flush_func Optional - E.g. LASIpFlush or NULL
+ * OUTPUT
+ * 0 on success, non-zero on failure
+ */
+NSAPI_PUBLIC int
+ACL_LasRegister(NSErr_t *errp, char *attr_name, LASEvalFunc_t eval_func,
+LASFlushFunc_t flush_func)
+{
+
+ if ((!attr_name) || (!eval_func)) return -1;
+
+ ACL_CritEnter();
+
+ /* See if the function is already registered. If so, report and
+ * error, but go ahead and replace it.
+ */
+ if (PR_HashTableLookup(ACLLasEvalHash, attr_name) != NULL) {
+ nserrGenerate(errp, ACLERRDUPSYM, ACLERR3900, ACL_Program, 1,
+ attr_name);
+ }
+
+ /* Put it in the hash tables */
+ PR_HashTableAdd(ACLLasEvalHash, attr_name, (void *)eval_func);
+ PR_HashTableAdd(ACLLasFlushHash, attr_name, (void *)flush_func);
+
+ ACL_CritExit();
+ return 0;
+}
+
+/* ACL_LasFindEval
+ * INPUT
+ * errp NSError pointer
+ * attr_name E.g. "ip" or "user" etc.
+ * eval_funcp Where the function pointer is returned. NULL if the
+ * function isn't registered.
+ * Must be called in a critical section as ACLEvalHash is a global
+ * variable.
+ * OUTPUT
+ * 0 on success, non-zero on failure
+ */
+NSAPI_PUBLIC int
+ACL_LasFindEval(NSErr_t *errp, char *attr_name, LASEvalFunc_t *eval_funcp)
+{
+
+ NS_ASSERT(attr_name);
+ if (!attr_name) return -1;
+
+ *eval_funcp = (LASEvalFunc_t)PR_HashTableLookup(ACLLasEvalHash, attr_name);
+ return 0;
+}
+
+
+/* ACL_LasFindFlush
+ * INPUT
+ * errp NSError pointer
+ * attr_name E.g. "ip" or "user" etc.
+ * eval_funcp Where the function pointer is returned. NULL if the
+ * function isn't registered.
+ * OUTPUT
+ * 0 on success, non-zero on failure
+ */
+NSAPI_PUBLIC int
+ACL_LasFindFlush(NSErr_t *errp, char *attr_name, LASFlushFunc_t *flush_funcp)
+{
+
+ NS_ASSERT(attr_name);
+ if (!attr_name) return -1;
+
+ *flush_funcp = (LASFlushFunc_t)PR_HashTableLookup(ACLLasFlushHash, attr_name);
+ return 0;
+}
+
+
+/* ACL_MethodRegister
+ * INPUT
+ * name Method name string. Can be freed after return.
+ * OUTPUT
+ * &t Place to return the Method_t (>0)
+ * retcode 0 on success, non-zero otherwise
+ */
+
+int cur_method = 0; /* Use a static counter to generate the numbers */
+
+NSAPI_PUBLIC int
+ACL_MethodRegister(NSErr_t *errp, const char *name, ACLMethod_t *t)
+{
+ ACLMethod_t rv;
+
+ ACL_CritEnter();
+
+ /* See if this is already registered */
+ rv = (ACLMethod_t) PR_HashTableLookup(ACLMethodHash, name);
+ if (rv != NULL) {
+ *t = rv;
+ ACL_CritExit();
+ return 0;
+ }
+
+ /* To prevent the hash table from resizing, don't get to 32 entries */
+ if (cur_method >= (ACL_MAX_METHOD-1)) {
+ ACL_CritExit();
+ return -1;
+ }
+
+ /* Put it in the hash table */
+ rv = PR_HashTableAdd(ACLMethodHash, name, (void *)++cur_method);
+ *t = (ACLMethod_t) cur_method;
+
+ ACL_CritExit();
+ return 0;
+}
+
+NSAPI_PUBLIC int
+ACL_MethodFind(NSErr_t *errp, const char *name, ACLMethod_t *t)
+{
+ ACLMethod_t rv;
+
+ /* Don't have to get the Critical Section lock 'cause the only danger
+ * would be if the hash table had to be resized. We created it with
+ * room for 32 entries before that happens.
+ */
+ rv = (ACLMethod_t) PR_HashTableLookup(ACLMethodHash, name);
+ if (rv != NULL) {
+ *t = rv;
+ return 0;
+ }
+
+ return -1;
+}
+
+typedef struct HashEnumArg_s {
+ char **names;
+ int count;
+} HashEnumArg_t;
+
+typedef HashEnumArg_t *HashEnumArg_p;
+
+static int acl_hash_enumerator (PLHashEntry *he, PRIntn i, void *arg)
+{
+ HashEnumArg_t *info = (HashEnumArg_t *)arg;
+ char **names = info->names;
+
+ names[info->count++] = STRDUP((const char *)he->key);
+
+ return names[info->count-1] ? 0 : -1;
+}
+
+int acl_registered_names(PLHashTable *ht, int count, char ***names)
+{
+ HashEnumArg_t arg;
+ int rv;
+
+ if (count == 0) {
+ *names = 0;
+ return 0;
+ }
+
+ arg.names = (char **)MALLOC(count * sizeof(char *));
+ arg.count = 0;
+
+ if (!arg.names) return -1;
+
+ rv = PR_HashTableEnumerateEntries(ht, acl_hash_enumerator, &arg);
+
+ if (rv >= 0) {
+ /* success */
+ *names = arg.names;
+ }
+ else {
+ *names = 0;
+ }
+
+ return rv;
+}
+
+NSAPI_PUBLIC int
+ACL_MethodNamesGet(NSErr_t *errp, char ***names, int *count)
+{
+ *count = cur_method;
+ return acl_registered_names (ACLMethodHash, *count, names);
+}
+
+NSAPI_PUBLIC int
+ACL_MethodNamesFree(NSErr_t *errp, char **names, int count)
+{
+ int i;
+
+ if (!names) return 0;
+
+ for (i = count-1; i; i--) FREE(names[i]);
+
+ FREE(names);
+ return 0;
+}
+
+NSAPI_PUBLIC int
+ACL_DbTypeFind(NSErr_t *errp, const char *name, ACLDbType_t *t)
+{
+ ACLDbType_t rv;
+
+ /* Don't have to get the Critical Section lock 'cause the only danger
+ * would be if the hash table had to be resized. We created it with
+ * room for 32 entries before that happens.
+ */
+ rv = (ACLDbType_t) PR_HashTableLookup(ACLDbTypeHash, name);
+ if (rv != NULL) {
+ *t = rv;
+ return 0;
+ }
+
+ return -1;
+}
+
+/* ACL_DbTypeRegister
+ * INPUT
+ * name DbType name string. Can be freed after return.
+ * OUTPUT
+ * &t Place to return the DbType (>0)
+ * retcode 0 on success, non-zero otherwise
+ */
+
+int cur_dbtype = 0; /* Use a static counter to generate the numbers */
+
+NSAPI_PUBLIC int
+ACL_DbTypeRegister(NSErr_t *errp, const char *name, DbParseFn_t func, ACLDbType_t *t)
+{
+ ACLDbType_t rv;
+
+ ACL_CritEnter();
+
+ /* See if this is already registered */
+ rv = (ACLDbType_t) PR_HashTableLookup(ACLDbTypeHash, name);
+ if (rv != NULL) {
+ *t = rv;
+ ACLDbParseFnTable[(int)(PRSize)rv] = func;
+ ACL_CritExit();
+ return 0;
+ }
+
+ /* To prevent the hash table from resizing, don't get to 32 entries */
+ if (cur_dbtype >= (ACL_MAX_DBTYPE-1)) {
+ ACL_CritExit();
+ return -1;
+ }
+
+ /* Put it in the hash table */
+ rv = PR_HashTableAdd(ACLDbTypeHash, name, (void *)++cur_dbtype);
+ *t = (ACLDbType_t) cur_dbtype;
+ ACLDbParseFnTable[cur_dbtype] = func;
+
+ ACL_CritExit();
+ return 0;
+}
+
+
+NSAPI_PUBLIC int
+ACL_DbTypeIsRegistered (NSErr_t *errp, const ACLDbType_t t)
+{
+ return (0 < ((int)(PRSize)t) && ((int)(PRSize)t) <= cur_dbtype);
+}
+
+
+/* ACL_MethodIsEqual
+ * RETURNS non-zero if equal.
+ */
+NSAPI_PUBLIC int
+ACL_MethodIsEqual(NSErr_t *errp, const ACLMethod_t t1, const ACLMethod_t t2)
+{
+ return (t1 == t2);
+}
+
+
+/* ACL_DbTypeIsEqual
+ * RETURNS non-zero if equal.
+ */
+NSAPI_PUBLIC int
+ACL_DbTypeIsEqual(NSErr_t *errp, const ACLDbType_t t1, const ACLDbType_t t2)
+{
+ return (t1 == t2);
+}
+
+
+/* ACL_MethodNameIsEqual
+ * Takes a method type and a method name and sees if they match.
+ * Returns non-zero on match.
+ */
+NSAPI_PUBLIC int
+ACL_MethodNameIsEqual(NSErr_t *errp, const ACLMethod_t t1, const char *name)
+{
+ int rv;
+ ACLMethod_t t2;
+
+ rv = ACL_MethodFind(errp, name, &t2);
+ if (rv)
+ return (rv);
+ else
+ return (t1 == t2);
+}
+
+/* ACL_DbTypeNameIsEqual
+ * Takes a dbtype type and a dbtype name and sees if they match.
+ * Returns non-zero on match.
+ */
+NSAPI_PUBLIC int
+ACL_DbTypeNameIsEqual(NSErr_t *errp, const ACLDbType_t t1, const char *name)
+{
+ int rv;
+ ACLDbType_t t2;
+
+ rv = ACL_DbTypeFind(errp, name, &t2);
+ if (rv)
+ return (rv);
+ else
+ return (t1 == t2);
+}
+
+/* ACL_MethodGetDefault
+ */
+NSAPI_PUBLIC ACLMethod_t
+ACL_MethodGetDefault(NSErr_t *errp)
+{
+ return (ACLMethodDefault);
+}
+
+/* ACL_MethodSetDefault
+ */
+NSAPI_PUBLIC int
+ACL_MethodSetDefault(NSErr_t *errp, const ACLMethod_t t)
+{
+ ACLMethodDefault = t;
+ return 0;
+}
+
+
+/* ACL_DbTypeGetDefault
+ */
+NSAPI_PUBLIC ACLDbType_t
+ACL_DbTypeGetDefault(NSErr_t *errp)
+{
+ return (ACLDbTypeDefault);
+}
+
+/* ACL_DbTypeSetDefault
+ */
+NSAPI_PUBLIC int
+ACL_DbTypeSetDefault(NSErr_t *errp, ACLDbType_t t)
+{
+ ACLDbTypeDefault = t;
+ return 0;
+}
+
+
+/* ACL_DatabaseGetDefault
+ */
+NSAPI_PUBLIC const char *
+ACL_DatabaseGetDefault(NSErr_t *errp)
+{
+ return (ACLDatabaseDefault);
+}
+
+/* ACL_DatabaseSetDefault
+ */
+NSAPI_PUBLIC int
+ACL_DatabaseSetDefault(NSErr_t *errp, const char *dbname)
+{
+ ACLDbType_t dbtype;
+ int rv;
+ void *db;
+
+ if (!dbname || !*dbname) return LAS_EVAL_FAIL;
+
+ rv = ACL_DatabaseFind(errp, dbname, &dbtype, &db);
+
+ if (rv != LAS_EVAL_TRUE) return -1;
+
+ if (ACLDatabaseDefault) pool_free(ACL_DATABASE_POOL, ACLDatabaseDefault);
+
+ ACL_DbTypeSetDefault(errp, dbtype);
+ ACLDatabaseDefault = pool_strdup(ACL_DATABASE_POOL, dbname);
+
+ return ACLDatabaseDefault ? 0 : -1;
+}
+
+
+/* ACL_AuthInfoGetMethod
+ * INPUT
+ * auth_info A PList of the authentication name/value pairs as
+ * provided by EvalTestRights to the LAS.
+ * OUTPUT
+ * *t The Method number. This can be the default method
+ number if the auth_info PList doesn't explicitly have a Method entry.
+ * retcode 0 on success.
+ */
+NSAPI_PUBLIC int
+ACL_AuthInfoGetMethod(NSErr_t *errp, PList_t auth_info, ACLMethod_t *t)
+{
+ ACLMethod_t *methodp;
+
+ if (!auth_info ||
+ PListGetValue(auth_info, ACL_ATTR_METHOD_INDEX, (void **)&methodp, NULL) < 0)
+ {
+ /* No entry for "method" */
+ *t = ACLMethodDefault;
+ } else {
+ *t = *methodp;
+ }
+
+ return 0;
+}
+
+
+/* ACL_AuthInfoSetMethod
+ * INPUT
+ * auth_info A PList of the authentication name/value pairs as
+ * provided by EvalTestRights to the LAS.
+ * t The Method number.
+ * OUTPUT
+ * retcode 0 on success.
+ */
+NSAPI_PUBLIC int
+ACL_AuthInfoSetMethod(NSErr_t *errp, PList_t auth_info, ACLMethod_t t)
+{
+ ACLMethod_t *methodp;
+ int rv;
+
+ if (auth_info) {
+ rv = PListGetValue(auth_info, ACL_ATTR_METHOD_INDEX, (void **)&methodp,
+ NULL);
+
+ if (rv < 0) {
+ /* No entry for "method" */
+ methodp = (ACLMethod_t *)PERM_MALLOC(sizeof(ACLMethod_t));
+ if (!methodp) return -1;
+ *methodp = t;
+ PListInitProp(auth_info, ACL_ATTR_METHOD_INDEX, ACL_ATTR_METHOD, methodp, 0);
+ }
+ else {
+ /* replace the old entry */
+ if (!methodp) return -1;
+ *methodp = t;
+ }
+ }
+ else {
+ return -1;
+ }
+
+ return 0;
+}
+
+
+/* ACL_AuthInfoSetDbname
+ * INPUT
+ * auth_info A PList of the authentication name/value pairs as
+ * provided by EvalTestRights to the LAS.
+ * dbname Name of the new auth_info database.
+ * OUTPUT
+ * retcode 0 on success.
+ */
+NSAPI_PUBLIC int
+ACL_AuthInfoSetDbname(NSErr_t *errp, PList_t auth_info, const char *dbname)
+{
+ ACLDbType_t *dbtype = (ACLDbType_t *)PERM_MALLOC(sizeof(ACLDbType_t));
+ ACLDbType_t *t2;
+ char *copy;
+ char *n2;
+ void *db;
+ int old1;
+ int old2;
+ int rv;
+
+ if (!dbtype) {
+ /* out of memory */
+ return -1;
+ }
+
+ if (auth_info) {
+ rv = ACL_DatabaseFind(errp, dbname, dbtype, (void **)&db);
+
+ if (rv != LAS_EVAL_TRUE) {
+ PERM_FREE(dbtype);
+ return -1;
+ }
+
+ /* Check the existing entry */
+ old1 = PListGetValue(auth_info, ACL_ATTR_DBTYPE_INDEX, (void **)&t2,
+ NULL);
+ old2 = PListGetValue(auth_info, ACL_ATTR_DATABASE_INDEX, (void **)&n2,
+ NULL);
+
+ if (old1 >= 0 && old2 >= 0) {
+ /* check if the old entry is same */
+ if (ACL_DbTypeIsEqual(errp, *dbtype, *t2)) {
+ /* Nothing to do */
+ PERM_FREE(dbtype);
+ return 0;
+ }
+ }
+ /* free the old entries */
+ if (old1 >= 0) {
+ PListDeleteProp(auth_info, ACL_ATTR_DBTYPE_INDEX, ACL_ATTR_DBTYPE);
+ PERM_FREE(t2);
+ }
+ if (old2 >= 0) {
+ PListDeleteProp(auth_info, ACL_ATTR_DATABASE_INDEX, ACL_ATTR_DATABASE);
+ PERM_FREE(n2);
+ }
+
+ /* Create new entries for "dbtype" & "dbname" */
+ copy = (char *)PERM_STRDUP(dbname);
+ if (!copy) return -1;
+ PListInitProp(auth_info, ACL_ATTR_DATABASE_INDEX,
+ ACL_ATTR_DATABASE, copy, 0);
+ PListInitProp(auth_info, ACL_ATTR_DBTYPE_INDEX, ACL_ATTR_DBTYPE,
+ dbtype, 0);
+ }
+ else {
+ return -1;
+ }
+
+ return 0;
+}
+
+
+/* ACL_AuthInfoGetDbType
+ * INPUT
+ * auth_info A PList of the authentication name/value pairs as
+ * provided by EvalTestRights to the LAS.
+ * OUTPUT
+ * *t The DbType number. This can be the default dbtype
+ * number if the auth_info PList doesn't explicitly
+ * have a DbType entry.
+ * retcode 0 on success.
+ */
+NSAPI_PUBLIC int
+ACL_AuthInfoGetDbType(NSErr_t *errp, PList_t auth_info, ACLDbType_t *t)
+{
+ ACLDbType_t *dbtypep;
+
+ if (!auth_info ||
+ PListGetValue(auth_info, ACL_ATTR_DBTYPE_INDEX, (void **)&dbtypep, NULL) < 0)
+ {
+ /* No entry for "dbtype" */
+ *t = ACLDbTypeDefault;
+ } else {
+ *t = *dbtypep;
+ }
+
+ return 0;
+}
+
+/* ACL_AuthInfoGetDbname
+ * INPUT
+ * auth_info A PList of the authentication name/value pairs as
+ * provided by EvalTestRights to the LAS.
+ * OUTPUT
+ * dbname The database name. This can be the default database
+ * name if the auth_info PList doesn't explicitly
+ * have a database entry.
+ * retcode 0 on success.
+ */
+NSAPI_PUBLIC int
+ACL_AuthInfoGetDbname(PList_t auth_info, char **dbname)
+{
+ char *dbstr;
+
+ if (!auth_info ||
+ PListGetValue(auth_info, ACL_ATTR_DATABASE_INDEX, (void **)&dbstr, NULL) < 0)
+ {
+ /* No entry for "database" */
+ dbstr = ACLDatabaseDefault;
+ }
+
+ /* else the value was already set by the PListGetValue call */
+ *dbname = dbstr;
+ return 0;
+}
+
+NSAPI_PUBLIC DbParseFn_t
+ACL_DbTypeParseFn(NSErr_t *errp, const ACLDbType_t dbtype)
+{
+ if (ACL_DbTypeIsRegistered(errp, dbtype))
+ return ACLDbParseFnTable[(int)(PRSize)dbtype];
+ else
+ return 0;
+}
+
+/* The hash table is keyed by attribute name, and contains pointers to the
+ * PRCList headers. These in turn, circularly link a set of AttrGetter_s
+ * structures.
+ */
+NSAPI_PUBLIC int
+ACL_AttrGetterRegister(NSErr_t *errp, const char *attr, ACLAttrGetterFn_t fn,
+ ACLMethod_t m, ACLDbType_t d, int position, void *arg)
+{
+ ACLAttrGetter_t *getter;
+ PLHashEntry **hep;
+
+ if (position != ACL_AT_FRONT && position != ACL_AT_END) {
+ return -1;
+ }
+
+ ACL_CritEnter();
+
+ hep = PR_HashTableRawLookup(ACLAttrGetterHash, PR_HashCaseString(attr), attr);
+
+ /* Now, allocate the current entry */
+ getter = (ACLAttrGetter_t *)CALLOC(sizeof(ACLAttrGetter_t));
+ if (getter == NULL) {
+ ACL_CritExit();
+ return -1;
+ }
+ getter->method = m;
+ getter->dbtype = d;
+ getter->fn = fn;
+ getter->arg = arg;
+
+ if (*hep == 0) { /* New entry */
+
+ PR_INIT_CLIST(&getter->list);
+ PR_HashTableAdd(ACLAttrGetterHash, attr, (void *)getter);
+ }
+ else {
+
+ ACLAttrGetter_t *head = (ACLAttrGetter_t *)((*hep)->value);
+
+ PR_INSERT_BEFORE(&getter->list, &head->list);
+
+ if (position == ACL_AT_FRONT) {
+
+ /* Set new head of list */
+ (*hep)->value = (void *)getter;
+ }
+ }
+
+ ACL_CritExit();
+ return 0;
+}
+
+NSAPI_PUBLIC int
+ACL_AttrGetterFind(NSErr_t *errp, const char *attr,
+ ACLAttrGetterList_t *getters)
+{
+ *getters = PR_HashTableLookup(ACLAttrGetterHash, attr);
+ if (*getters)
+ return 0;
+ else
+ return -1;
+}
+
+NSAPI_PUBLIC
+ACLAttrGetter_t * ACL_AttrGetterFirst(ACLAttrGetterList_t *getters)
+{
+ ACLAttrGetter_t * first = 0;
+
+ if (getters && *getters) {
+
+ first = (ACLAttrGetter_t *)(*getters);
+ }
+
+ return first;
+}
+
+NSAPI_PUBLIC ACLAttrGetter_t *
+ACL_AttrGetterNext(ACLAttrGetterList_t *getters, ACLAttrGetter_t *last)
+{
+ ACLAttrGetter_t *head;
+ ACLAttrGetter_t *next = 0;
+
+ if (getters && *getters && last) {
+
+ head = (ACLAttrGetter_t *)(*getters);
+ if (head) {
+
+ /* End of list? */
+ if (last != (ACLAttrGetter_t *)PR_LIST_TAIL(&head->list)) {
+
+ /* No, get next entry */
+ next = (ACLAttrGetter_t *)PR_NEXT_LINK(&last->list);
+ }
+ }
+ }
+
+ return next;
+}
+
+int
+ACL_RegisterInit ()
+{
+ NSErr_t *errp = 0;
+ int rv;
+
+ /* Register the ldap database */
+ rv = ACL_DbTypeRegister(errp, ACL_DBTYPE_LDAP, parse_ldap_url, &ACL_DbTypeLdap);
+
+ return rv;
+}
+