summaryrefslogtreecommitdiffstats
path: root/ldap/servers/slapd/rootdse.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/slapd/rootdse.c
downloadds-b2093e3016027d6b5cf06b3f91f30769bfc099e2.tar.gz
ds-b2093e3016027d6b5cf06b3f91f30769bfc099e2.tar.xz
ds-b2093e3016027d6b5cf06b3f91f30769bfc099e2.zip
Moving NSCP Directory Server from DirectoryBranch to TRUNK, initial drop. (foxworth)ldapserver7x
Diffstat (limited to 'ldap/servers/slapd/rootdse.c')
-rw-r--r--ldap/servers/slapd/rootdse.c331
1 files changed, 331 insertions, 0 deletions
diff --git a/ldap/servers/slapd/rootdse.c b/ldap/servers/slapd/rootdse.c
new file mode 100644
index 00000000..f438cceb
--- /dev/null
+++ b/ldap/servers/slapd/rootdse.c
@@ -0,0 +1,331 @@
+/** BEGIN COPYRIGHT BLOCK
+ * Copyright 2001 Sun Microsystems, Inc.
+ * Portions copyright 1999, 2001-2003 Netscape Communications Corporation.
+ * All rights reserved.
+ * END COPYRIGHT BLOCK **/
+/* 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",
+ "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 */
+ }
+
+ if ( NULL == readonly_attributes ) {
+ return 0;
+ }
+
+ /*
+ * 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);
+ }
+
+ 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 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 */
+}