summaryrefslogtreecommitdiffstats
path: root/ldap/servers/plugins/acl/aclplugin.c
diff options
context:
space:
mode:
authorcvsadm <cvsadm>2005-01-21 00:44:34 +0000
committercvsadm <cvsadm>2005-01-21 00:44:34 +0000
commitb2093e3016027d6b5cf06b3f91f30769bfc099e2 (patch)
treecf58939393a9032182c4fbc4441164a9456e82f8 /ldap/servers/plugins/acl/aclplugin.c
downloadds-ldapserver7x.tar.gz
ds-ldapserver7x.tar.xz
ds-ldapserver7x.zip
Moving NSCP Directory Server from DirectoryBranch to TRUNK, initial drop. (foxworth)ldapserver7x
Diffstat (limited to 'ldap/servers/plugins/acl/aclplugin.c')
-rw-r--r--ldap/servers/plugins/acl/aclplugin.c355
1 files changed, 355 insertions, 0 deletions
diff --git a/ldap/servers/plugins/acl/aclplugin.c b/ldap/servers/plugins/acl/aclplugin.c
new file mode 100644
index 00000000..a39ef3cd
--- /dev/null
+++ b/ldap/servers/plugins/acl/aclplugin.c
@@ -0,0 +1,355 @@
+/** BEGIN COPYRIGHT BLOCK
+ * Copyright 2001 Sun Microsystems, Inc.
+ * Portions copyright 1999, 2001-2003 Netscape Communications Corporation.
+ * All rights reserved.
+ * END COPYRIGHT BLOCK **/
+/*
+ * There are 3 ACL PLUGIN points
+ * PREOP, POSTOP and ACL plugin
+ *
+ */
+#include "acl.h"
+#include "dirver.h"
+#include <dirlite_strings.h> /* PLUGIN_MAGIC_VENDOR_STR */
+
+static Slapi_PluginDesc pdesc = { "acl", PLUGIN_MAGIC_VENDOR_STR, PRODUCTTEXT, "acl access check plugin" };
+char *plugin_name = ACL_PLUGIN_NAME;
+
+/* Prototypes */
+
+static int aclplugin_preop_search ( Slapi_PBlock *pb );
+static int aclplugin_preop_modify ( Slapi_PBlock *pb );
+static int aclplugin_preop_common ( Slapi_PBlock *pb );
+
+/*******************************************************************************
+ * ACL PLUGIN Architecture
+ *
+ * There are 3 registered plugins:
+ *
+ * 1) PREOP ACL Plugin
+ * The preop plugin does all the initialization. It allocate the ACL
+ * PBlock and copies stuff from the connection if it needs to.
+ *
+ * 2) POSTOP ACL Plugin
+ * The Postop plugin cleans up the ACL PBlock. It copies Back to the
+ * connection struct. The Postop bind & Unbind cleans up the
+ * ACL CBlock ( struct hanging from conn struct ).
+ *
+ * 3) ACCESSCONTROL Plugin
+ * Main module which does the access check. There are 5 entry point
+ * from this plugin
+ * a) Initilize the ACL system i.e read all the ACLs and generate the
+ * the ACL List.
+ * b) Check for ACI syntax.
+ * c) Check for normal access.
+ * d) Check for access to a mod request.
+ * e) Update the in-memory ACL List.
+ *
+ *******************************************************************************/
+
+/*******************************************************************************
+ * PREOP
+ *******************************************************************************/
+
+/* Plugin identity is passed by the server in the plugin init function and must
+ be supplied by the plugin to all internal operations it initiates
+ */
+void* g_acl_preop_plugin_identity;
+
+int
+acl_preopInit (Slapi_PBlock *pb)
+{
+ int rc = 0;
+
+ /* save plugin identity to later pass to internal operations */
+ rc = slapi_pblock_get (pb, SLAPI_PLUGIN_IDENTITY, &g_acl_preop_plugin_identity);
+
+ /* Declare plugin version */
+ rc = slapi_pblock_set(pb, SLAPI_PLUGIN_VERSION, SLAPI_PLUGIN_VERSION_01);
+
+ /* Provide descriptive information */
+ rc |= slapi_pblock_set(pb, SLAPI_PLUGIN_DESCRIPTION, (void*)&pdesc);
+
+ /* Register functions */
+ rc |= slapi_pblock_set(pb, SLAPI_PLUGIN_PRE_SEARCH_FN, (void*)aclplugin_preop_search);
+ rc |= slapi_pblock_set(pb, SLAPI_PLUGIN_PRE_COMPARE_FN, (void*)aclplugin_preop_search);
+ rc |= slapi_pblock_set(pb, SLAPI_PLUGIN_PRE_ADD_FN, (void*)aclplugin_preop_modify);
+ rc |= slapi_pblock_set(pb, SLAPI_PLUGIN_PRE_MODIFY_FN, (void*)aclplugin_preop_modify);
+ rc |= slapi_pblock_set(pb, SLAPI_PLUGIN_PRE_MODRDN_FN, (void*)aclplugin_preop_modify);
+ rc |= slapi_pblock_set(pb, SLAPI_PLUGIN_PRE_DELETE_FN, (void*)aclplugin_preop_modify);
+
+#if 0
+ /*
+ * XXXmcs: In order to support access control checking from
+ * extended operations, we need a SLAPI_PLUGIN_PRE_EXTENDED_FN hook.
+ * But today no such entry point exists.
+ */
+ rc |= slapi_pblock_set(pb, SLAPI_PLUGIN_PRE_EXTENDED_FN, (void*)aclplugin_preop_modify);
+#endif
+
+
+ slapi_log_error( SLAPI_LOG_PLUGIN, plugin_name, "<= acl_preop_Init %d\n", rc, 0, 0 );
+ return( rc );
+}
+
+/* For preop search we do two things:
+ * 1) based on the search base, we preselect the acls.
+ * 2) also get hold of a acl_pblock for use
+ */
+static int
+aclplugin_preop_search ( Slapi_PBlock *pb )
+{
+ int scope;
+ char *base = NULL;
+ int optype;
+ int isRoot;
+ int rc = 0;
+
+ TNF_PROBE_0_DEBUG(aclplugin_preop_search_start ,"ACL","");
+
+ slapi_pblock_get ( pb, SLAPI_OPERATION_TYPE, &optype );
+ slapi_pblock_get ( pb, SLAPI_REQUESTOR_ISROOT, &isRoot );
+
+ if ( isRoot ) {
+ TNF_PROBE_1_DEBUG(aclplugin_preop_search_end ,"ACL","",
+ tnf_string,isroot,"");
+ return rc;
+ }
+
+ slapi_pblock_get( pb, SLAPI_SEARCH_TARGET, &base );
+ /* For anonymous client doing search nothing needs to be set up */
+ if ( optype == SLAPI_OPERATION_SEARCH && aclanom_is_client_anonymous ( pb ) &&
+ ! slapi_dn_issuffix( base, "cn=monitor") ) {
+ TNF_PROBE_1_DEBUG(aclplugin_preop_search_end ,"ACL","",
+ tnf_string,anon,"");
+ return rc;
+ }
+
+ if ( 0 == ( rc = aclplugin_preop_common( pb ))) {
+ slapi_pblock_get( pb, SLAPI_SEARCH_SCOPE, &scope );
+ acllist_init_scan ( pb, scope, base );
+ }
+
+ TNF_PROBE_0_DEBUG(aclplugin_preop_search_end ,"ACL","");
+
+ return rc;
+}
+
+/*
+ * For rest of the opertion type, we get a hold of the acl
+ * private Block.
+ */
+static int
+aclplugin_preop_modify ( Slapi_PBlock *pb )
+{
+ /*
+ * Note: since we don't keep the anom profile for modifies, we have to go
+ * through the regular process to check the access.
+ */
+ return aclplugin_preop_common( pb );
+}
+
+/*
+ * Common function that is called by aclplugin_preop_search() and
+ * aclplugin_preop_modify().
+ *
+ * Return values:
+ * 0 - all is well; proceed.
+ * 1 - fatal error; result has been sent to client.
+ */
+static int
+aclplugin_preop_common( Slapi_PBlock *pb )
+{
+ char *proxy_dn; /* id being assumed */
+ char *dn; /* proxy master */
+ char *errtext = NULL;
+ int lderr;
+ Acl_PBlock *aclpb;
+
+ TNF_PROBE_0_DEBUG(aclplugin_preop_common_start ,"ACL","");
+
+ aclpb = acl_get_aclpb ( pb, ACLPB_BINDDN_PBLOCK );
+
+ /*
+ * The following mallocs memory for proxy_dn, but not the dn.
+ * The proxy_dn is the id being assumed, while dn
+ * is the "proxy master".
+ */
+ proxy_dn = NULL;
+ if ( LDAP_SUCCESS != ( lderr = acl_get_proxyauth_dn( pb, &proxy_dn,
+ &errtext ))) {
+ /*
+ * Fatal error -- send a result to the client and arrange to skip
+ * any further processing.
+ */
+ slapi_send_ldap_result( pb, lderr, NULL, errtext, 0, NULL );
+ TNF_PROBE_1_DEBUG(aclplugin_preop_common_end ,"ACL","",
+ tnf_string,proxid_error,"");
+
+ return 1; /* skip any further processing */
+ }
+ slapi_pblock_get ( pb, SLAPI_REQUESTOR_DN, &dn );
+
+
+ /*
+ * The dn is copied into the aclpb during initialization.
+ */
+ if ( proxy_dn) {
+ TNF_PROBE_0_DEBUG(proxyacpb_init_start,"ACL","");
+
+ slapi_log_error( SLAPI_LOG_ACL, plugin_name,
+ "proxied authorization dn is (%s)\n", proxy_dn );
+ acl_init_aclpb ( pb, aclpb, proxy_dn, 1 );
+ aclpb = acl_new_proxy_aclpb (pb );
+ acl_init_aclpb ( pb, aclpb, dn, 0 );
+ slapi_ch_free ( (void **) &proxy_dn );
+
+ TNF_PROBE_0_DEBUG(proxyacpb_init_end,"ACL","");
+
+ } else {
+ TNF_PROBE_0_DEBUG(aclpb_init_start,"ACL","");
+ acl_init_aclpb ( pb, aclpb, dn, 1 );
+ TNF_PROBE_0_DEBUG(aclpb_init_end,"ACL","");
+
+ }
+
+ TNF_PROBE_0_DEBUG(aclplugin_preop_common_end ,"ACL","");
+
+ return 0;
+}
+
+/*******************************************************************************
+ * POSTOP
+ *******************************************************************************/
+
+/*******************************************************************************
+ * ACCESSCONTROL PLUGIN
+ *******************************************************************************/
+
+void* g_acl_plugin_identity;
+
+/* For now, the acl component is implemented as 2 different plugins */
+/* Return the right plugin identity */
+void * aclplugin_get_identity(int plug) {
+ if (plug == ACL_PLUGIN_IDENTITY)
+ return g_acl_plugin_identity;
+ if (plug == ACL_PREOP_PLUGIN_IDENTITY)
+ return g_acl_preop_plugin_identity;
+ return NULL;
+}
+
+int
+aclplugin_init (Slapi_PBlock *pb )
+{
+
+ int rc = 0; /* OK */
+ rc = aclinit_main ( pb );
+
+ return rc;
+
+}
+int
+aclplugin_stop ( Slapi_PBlock *pb )
+{
+ int rc = 0; /* OK */
+
+ /* nothing to be done now */
+ return rc;
+}
+
+int
+acl_init( Slapi_PBlock *pb )
+{
+ int rc =0;
+
+ slapi_log_error( SLAPI_LOG_PLUGIN, plugin_name, "=> acl_init\n", 0, 0, 0 );
+
+ if ( 0 != acl_init_ext() ) {
+ slapi_log_error ( SLAPI_LOG_FATAL, plugin_name,
+ "Unable to initialize the extensions\n");
+ return 1;
+ }
+
+ /* save plugin identity to later pass to internal operations */
+ rc = slapi_pblock_get (pb, SLAPI_PLUGIN_IDENTITY, &g_acl_plugin_identity);
+
+ rc = slapi_pblock_set( pb, SLAPI_PLUGIN_VERSION,
+ (void *) SLAPI_PLUGIN_VERSION_01 );
+ rc |= slapi_pblock_set( pb, SLAPI_PLUGIN_DESCRIPTION,
+ (void *)&pdesc );
+
+ rc |= slapi_pblock_set( pb, SLAPI_PLUGIN_START_FN, (void *) aclplugin_init );
+ rc = slapi_pblock_set( pb, SLAPI_PLUGIN_CLOSE_FN, (void *) aclplugin_stop );
+ rc |= slapi_pblock_set( pb, SLAPI_PLUGIN_ACL_SYNTAX_CHECK,
+ (void *) acl_verify_aci_syntax );
+ rc |= slapi_pblock_set( pb, SLAPI_PLUGIN_ACL_ALLOW_ACCESS,
+ (void *) acl_access_allowed_main );
+ rc |= slapi_pblock_set( pb, SLAPI_PLUGIN_ACL_MODS_ALLOWED,
+ (void *) acl_check_mods );
+ rc |= slapi_pblock_set( pb, SLAPI_PLUGIN_ACL_MODS_UPDATE,
+ (void *) acl_modified );
+
+ slapi_log_error( SLAPI_LOG_PLUGIN, plugin_name, "<= acl_init %d\n", rc, 0, 0 );
+ return( rc );
+}
+
+/*
+ *
+ * acl_access_allowed_main
+ * Main interface to the plugin. Calls different access check functions
+ * based on the flag.
+ *
+ *
+ * Returns:
+ * LDAP_SUCCESS -- access is granted
+ * LDAP_INSUFFICIENT_ACCESS -- access denied
+ * <other ldap error> -- ex: opererations error
+ *
+ */
+int
+acl_access_allowed_main ( Slapi_PBlock *pb, Slapi_Entry *e, char **attrs,
+ struct berval *val, int access , int flags, char **errbuf)
+{
+ int rc =0;
+ char *attr = NULL;
+
+ TNF_PROBE_0_DEBUG(acl_access_allowed_main_start,"ACL","");
+
+ if (attrs && *attrs) attr = attrs[0];
+
+ if (ACLPLUGIN_ACCESS_READ_ON_ENTRY == flags)
+ rc = acl_read_access_allowed_on_entry ( pb, e, attrs, access);
+ else if ( ACLPLUGIN_ACCESS_READ_ON_ATTR == flags)
+ rc = acl_read_access_allowed_on_attr ( pb, e, attr, val, access);
+ else if ( ACLPLUGIN_ACCESS_READ_ON_VLV == flags)
+ rc = acl_access_allowed_disjoint_resource ( pb, e, attr, val, access);
+ else if ( ACLPLUGIN_ACCESS_MODRDN == flags)
+ rc = acl_access_allowed_modrdn ( pb, e, attr, val, access);
+ else if ( ACLPLUGIN_ACCESS_GET_EFFECTIVE_RIGHTS == flags)
+ rc = acl_get_effective_rights ( pb, e, attrs, val, access, errbuf );
+ else
+ rc = acl_access_allowed ( pb, e, attr, val, access);
+
+ /* generate the appropriate error message */
+ if ( ( rc != LDAP_SUCCESS ) && errbuf &&
+ ( ACLPLUGIN_ACCESS_GET_EFFECTIVE_RIGHTS != flags ) &&
+ ( access & ( SLAPI_ACL_WRITE | SLAPI_ACL_ADD | SLAPI_ACL_DELETE ))) {
+
+ char *edn = slapi_entry_get_dn ( e );
+
+ acl_gen_err_msg(access, edn, attr, errbuf);
+ }
+
+ TNF_PROBE_0_DEBUG(acl_access_allowed_main_end,"ACL","");
+
+ return rc;
+}
+#ifdef _WIN32
+
+int *module_ldap_debug = 0;
+void plugin_init_debug_level ( int *level_ptr )
+{
+ module_ldap_debug = level_ptr;
+}
+#endif
+