| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386 |
- /** BEGIN COPYRIGHT BLOCK
- * Copyright (C) 2001 Sun Microsystems, Inc. Used by permission.
- * Copyright (C) 2005 Red Hat, Inc.
- * All rights reserved.
- *
- * License: GPL (version 3 or any later version).
- * See LICENSE for details.
- * END COPYRIGHT BLOCK **/
- #ifdef HAVE_CONFIG_H
- # include <config.h>
- #endif
- /*
- * There are 3 ACL PLUGIN points
- * PREOP, POSTOP and ACL plugin
- *
- */
- #include "acl.h"
- static Slapi_PluginDesc pdesc = { "acl", VENDOR, DS_PACKAGE_VERSION, "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 );
- 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 );
- 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;
- const char *base = NULL;
- Slapi_DN *sdn = NULL;
- int optype;
- int isRoot;
- int isProxy = 0;
- int rc = 0;
- char *errtxt = NULL;
- char *proxy_dn = NULL;
-
- 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 (LDAP_SUCCESS == proxyauth_get_dn(pb, &proxy_dn, &errtxt) && proxy_dn) {
- isProxy = 1;
- }
- slapi_ch_free_string(&proxy_dn);
- if ( isRoot && !isProxy) {
- TNF_PROBE_1_DEBUG(aclplugin_preop_search_end ,"ACL","",
- tnf_string,isroot,"");
- return rc;
- }
- slapi_pblock_get( pb, SLAPI_SEARCH_TARGET_SDN, &sdn );
- base = slapi_sdn_get_dn(sdn);
- /* 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.
- */
- int
- aclplugin_preop_common( Slapi_PBlock *pb )
- {
- char *proxy_dn = NULL; /* 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 );
- if (aclpb == NULL) {
- slapi_log_error(SLAPI_LOG_ACL, plugin_name, "aclplugin_preop_common - Error: aclpb is NULL\n" );
- slapi_send_ldap_result( pb, LDAP_OPERATIONS_ERROR, NULL, NULL, 0, NULL );
- return 1;
- }
- /* See if we have initialized already */
- if ( aclpb->aclpb_state & ACLPB_INITIALIZED ) goto done;
- /*
- * 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".
- */
- if ( LDAP_SUCCESS != ( lderr = proxyauth_get_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,"");
- slapi_ch_free_string(&proxy_dn);
- 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,
- "aclplugin_preop_common - 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","");
- }
- done:
- 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();
- return rc;
- }
- int
- aclplugin_stop ( Slapi_PBlock *pb )
- {
- int rc = 0; /* OK */
- free_acl_avl_list();
- ACL_Destroy();
- acl_destroy_aclpb_pool();
- acl_remove_ext();
- ACL_AttrGetterHashDestroy();
- ACL_MethodHashDestroy();
- ACL_DestroyPools();
- aclanom__del_profile(1);
- aclgroup_free();
- //aclext_free_lockarray();
- acllist_free();
- return rc;
- }
- int
- acl_init( Slapi_PBlock *pb )
- {
- int rc =0;
- slapi_log_error(SLAPI_LOG_PLUGIN, plugin_name, "=> acl_init\n" );
- if ( 0 != acl_init_ext() ) {
- slapi_log_error(SLAPI_LOG_ERR, plugin_name,
- "acl_init - 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);
- 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) {
- if (attr == NULL) {
- slapi_log_error(SLAPI_LOG_PLUGIN, plugin_name, "acl_access_allowed_main - Missing attribute\n" );
- rc = LDAP_OPERATIONS_ERROR;
- } else {
- 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 | SLAPI_ACL_MODDN ))) {
- 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;
- }
|