| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354 |
- /** 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
- /* rootdse.c - routines to manage the root DSE */
- #include <stdio.h>
- #include "slap.h"
- #include "fe.h"
- /* XXXmcs: why not look at the NO-USER-MODIFICATION flag instead? */
- static char *readonly_attributes[] = {
- "namingcontexts",
- "nsBackendSuffix",
- "subschemasubentry",
- "supportedldapversion",
- "supportedcontrol",
- "supportedextension",
- "supportedfeatures",
- "supportedsaslmechanisms",
- "dataversion",
- "ref",
- "vendorName",
- "vendorVersion",
- ATTR_NETSCAPEMDSUFFIX,
- NULL
- };
- static char *writable_attributes[] = {
- "copiedfrom",
- "copyingfrom",
- "aci",
- NULL
- };
- /*
- * function: is_readonly_attr
- * args: attr - candidate attribute name
- * returns: 0 if this attribute may be written to the root DSE
- * 1 if it may not be written.
- * notes: should probably be integrated into syntax AVL tree, so that
- * this list can be configured at runtime.
- */
- static int
- rootdse_is_readonly_attr( char *attr )
- {
- int i;
- if ( NULL == attr ) {
- return 1; /* I guess. It's not really an attribute at all */
- }
- /*
- * optimization: check for attributes we're likely to be writing
- * frequently.
- */
- for ( i = 0; NULL != writable_attributes[ i ]; i++ ) {
- if ( strncasecmp( attr, writable_attributes[ i ],
- strlen( writable_attributes[ i ])) == 0 ) {
- return 0;
- }
- }
- for ( i = 0; NULL != readonly_attributes[ i ]; i++ ) {
- if ( strncasecmp( attr, readonly_attributes[ i ],
- strlen( readonly_attributes[ i ])) == 0 ) {
- return 1;
- }
- }
- return 0;
- }
- /*
- * Handle a read operation on the root DSE (the entry with DN "");
- * Note: we're copying a lot of attributes here. It might be better
- * to keep track of which we really need to free, and arrange that
- * the others are unlinked from the attribute list of the entry
- * before calling slapi_entry_free().
- */
- int
- read_root_dse( Slapi_PBlock *pb, Slapi_Entry *e, Slapi_Entry *entryAfter, int *returncode, char *returntext, void *arg )
- {
- int i;
- struct berval *vals[2];
- struct berval val;
- struct berval **bvals;
- Slapi_Backend *be;
- char *cookie = NULL;
- char **strs;
- void *node;
- Slapi_DN *sdn;
- /*
- * Check that we were doing a base search on the root dse.
- */
- {
- int scope;
- slapi_pblock_get( pb, SLAPI_SEARCH_SCOPE, &scope );
- if(scope!=LDAP_SCOPE_BASE)
- {
- *returncode= LDAP_NO_SUCH_OBJECT;
- return SLAPI_DSE_CALLBACK_ERROR;
- }
- }
- vals[0] = &val;
- vals[1] = NULL;
- /* loop through backend suffixes to get namingcontexts attr */
- attrlist_delete( &e->e_attrs, "namingcontexts");
- sdn = slapi_get_first_suffix(&node, 0);
- while (sdn)
- {
- val.bv_val = (char*)slapi_sdn_get_dn(sdn); /* jcm: had to cast away const */
- val.bv_len = strlen( val.bv_val );
- attrlist_merge( &e->e_attrs, "namingcontexts", vals );
- sdn = slapi_get_next_suffix(&node, 0);
- }
- val.bv_val = config_get_default_naming_context();
- if (val.bv_val) {
- val.bv_len = strlen(val.bv_val);
- attrlist_replace( &e->e_attrs, "defaultnamingcontext", vals );
- }
- attrlist_delete( &e->e_attrs, "nsBackendSuffix");
- for (be = slapi_get_first_backend(&cookie); be != NULL;
- be = slapi_get_next_backend(cookie)) {
- char * base;
- char * be_name;
- const Slapi_DN *be_suffix;
- if (slapi_be_private(be)) continue;
- /* tolerate a backend under construction containing no suffix */
- if ((be_suffix = slapi_be_getsuffix(be, 0)) == NULL) continue;
- if ((base = (char *)slapi_sdn_get_dn(be_suffix)) == NULL) continue;
- if ((be_name = slapi_be_get_name(be)) == NULL) continue;
- val.bv_len = strlen(base)+strlen(be_name)+1;
- val.bv_val = slapi_ch_malloc(val.bv_len+1);
- sprintf(val.bv_val, "%s:%s", be_name, base);
- attrlist_merge(&e->e_attrs, "nsBackendSuffix", vals);
- slapi_ch_free((void **) &val.bv_val);
- }
- slapi_ch_free((void **)&cookie);
- /* schema entry */
- val.bv_val = SLAPD_SCHEMA_DN;
- val.bv_len = sizeof( SLAPD_SCHEMA_DN ) - 1;
- attrlist_replace( &e->e_attrs, "subschemasubentry", vals );
-
- /* supported extended operations */
- attrlist_delete( &e->e_attrs, "supportedExtension");
- if (( strs = slapi_get_supported_extended_ops_copy()) != NULL ) {
- for ( i = 0; strs[i] != NULL; ++i ) {
- val.bv_val = strs[i];
- val.bv_len = strlen( strs[i] );
- attrlist_merge( &e->e_attrs, "supportedExtension", vals );
- }
- charray_free(strs);
- }
-
- /* supported controls */
- attrlist_delete( &e->e_attrs, "supportedControl");
- if ( slapi_get_supported_controls_copy( &strs, NULL ) == 0
- && strs != NULL ) {
- for ( i = 0; strs[i] != NULL; ++i ) {
- val.bv_val = strs[i];
- val.bv_len = strlen( strs[i] );
- attrlist_merge( &e->e_attrs, "supportedControl", vals );
- }
- charray_free(strs);
- }
- /* supported features */
- attrlist_delete( &e->e_attrs, "supportedFeatures");
- if ( slapi_get_supported_features_copy( &strs ) == 0
- && strs != NULL ) {
- for ( i = 0; strs[i] != NULL; ++i ) {
- val.bv_val = strs[i];
- val.bv_len = strlen( strs[i] );
- attrlist_merge( &e->e_attrs, "supportedFeatures", vals );
- }
- charray_free(strs);
- }
- /* supported sasl mechanisms */
- attrlist_delete( &e->e_attrs, "supportedSASLMechanisms");
- if (( strs = ids_sasl_listmech (pb)) != NULL ) {
- for ( i = 0; strs[i] != NULL; ++i ) {
- val.bv_val = strs[i];
- val.bv_len = strlen( strs[i] );
- attrlist_merge( &e->e_attrs, "supportedSASLMechanisms", vals );
- }
- charray_free(strs);
- }
- /* supported LDAP versions */
- val.bv_val = "2";
- val.bv_len = 1;
- attrlist_replace( &e->e_attrs, "supportedldapversion", vals );
- val.bv_val = "3";
- val.bv_len = 1;
- attrlist_merge( &e->e_attrs, "supportedldapversion", vals );
- /* superior references (ref attribute) */
- attrlist_delete( &e->e_attrs, "ref");
- if (( bvals = g_get_default_referral()) != NULL ) {
- for ( i = 0; bvals[i] != NULL; ++i ) {
- val.bv_val = bvals[i]->bv_val;
- val.bv_len = bvals[i]->bv_len;
- attrlist_merge( &e->e_attrs, "ref", vals );
- }
- }
- /* RFC 3045 attributes: vendorName and vendorVersion */
- val.bv_val = SLAPD_VENDOR_NAME;
- val.bv_len = strlen( val.bv_val );
- attrlist_replace( &e->e_attrs, "vendorName", vals );
- val.bv_val = slapd_get_version_value();
- val.bv_len = strlen( val.bv_val );
- attrlist_replace( &e->e_attrs, "vendorVersion", vals );
- slapi_ch_free( (void **)&val.bv_val );
- /* Server Data Version */
- if (( val.bv_val = (char*)get_server_dataversion()) != NULL ) { /* jcm cast away const */
- val.bv_len = strlen( val.bv_val );
- attrlist_replace( &e->e_attrs, attr_dataversion, vals );
- }
- /* machine data suffix
- * this has been added in 4.0 for replication purpose
- * and since 5.0 is now unused by the core server,
- * however some functionalities of the console framework 5.01
- * still depend on this
- */
- if (( val.bv_val = get_config_DN()) != NULL ) {
- val.bv_len = strlen( val.bv_val );
- attrlist_replace( &e->e_attrs, ATTR_NETSCAPEMDSUFFIX, vals );
- }
- #ifdef notdef
- /* XXXggood testing - print the size of the changelog db */
- {
- unsigned int clsize;
- clsize = get_changelog_size();
- sprintf( buf, "%u", clsize );
- val.bv_val = buf;
- val.bv_len = strlen( buf );
- attrlist_replace( &e->e_attrs, "changelogsize", vals );
- slapi_ch_free((void**)&val.bv_val );
- }
- #endif /* notdef */
- /* vlvsearch is list of dns to VLV Search Specifications */
- attrlist_delete( &e->e_attrs, "vlvsearch");
- cookie = NULL;
- be = slapi_get_first_backend(&cookie);
- while (be)
- {
- if(!be->be_private)
- {
- /* Generate searches to find the VLV Search Specifications */
- int r;
- Slapi_PBlock *resultpb= NULL;
- Slapi_Entry** entry = NULL;
- Slapi_DN dn;
- slapi_sdn_init(&dn);
- be_getconfigdn(be,&dn);
- resultpb= slapi_search_internal( slapi_sdn_get_ndn(&dn), LDAP_SCOPE_ONELEVEL, "objectclass=vlvsearch", NULL, NULL, 1);
- slapi_sdn_done(&dn);
- slapi_pblock_get( resultpb, SLAPI_PLUGIN_INTOP_SEARCH_ENTRIES, &entry );
- slapi_pblock_get( resultpb, SLAPI_PLUGIN_INTOP_RESULT, &r );
- if(r==LDAP_SUCCESS)
- {
- for (; *entry; ++entry)
- {
- val.bv_val = slapi_entry_get_dn(*entry);
- val.bv_len = strlen( val.bv_val );
- attrlist_merge( &e->e_attrs, "vlvsearch", vals );
- }
- }
- slapi_free_search_results_internal(resultpb);
- slapi_pblock_destroy(resultpb);
- }
- be = slapi_get_next_backend (cookie);
- }
- slapi_ch_free ((void **)&cookie);
- *returncode= LDAP_SUCCESS;
- return SLAPI_DSE_CALLBACK_OK;
- }
- /*
- * Handle a modification request on the root DSE. Only certain
- * attributes are writable. If an attempt to modify an attribute
- * which is not allowed, return LDAP_UNWILLING_TO_PERFORM, unless
- * the modification is disallowed because of ACL checking, in which
- * case LDAP_INSUFFICIENT_ACCESS is returned.
- */
- int
- modify_root_dse( Slapi_PBlock *pb, Slapi_Entry *entryBefore, Slapi_Entry *e, int *returncode, char *returntext, void *arg )
- {
- LDAPMod **mods;
- /*
- * Make a pass through the attributes and check them
- * to make sure none are computed. Also check for
- * reflected attributes and reject those as well.
- * Eventually, some reflected attributes might be
- * writable, but for now, none are.
- */
- slapi_pblock_get( pb, SLAPI_MODIFY_MODS, &mods );
- if ( NULL != mods )
- {
- int i;
- for ( i = 0; NULL != mods[ i ]; i++ )
- {
- if ( rootdse_is_readonly_attr( mods[ i ]->mod_type ))
- {
- /* The modification is disallowed */
- *returncode = LDAP_UNWILLING_TO_PERFORM;
- strcpy(returntext,"Modification of these root DSE attributes not allowed");
- return SLAPI_DSE_CALLBACK_ERROR;
- }
- }
- }
- *returncode= LDAP_SUCCESS;
- return SLAPI_DSE_CALLBACK_OK; /* success -- apply the changes */
- }
|