diff options
Diffstat (limited to 'ldap/servers/plugins/acl/aclplugin.c')
-rw-r--r-- | ldap/servers/plugins/acl/aclplugin.c | 355 |
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 + |