diff options
author | cvsadm <cvsadm> | 2005-01-21 00:44:34 +0000 |
---|---|---|
committer | cvsadm <cvsadm> | 2005-01-21 00:44:34 +0000 |
commit | b2093e3016027d6b5cf06b3f91f30769bfc099e2 (patch) | |
tree | cf58939393a9032182c4fbc4441164a9456e82f8 /ldap/servers/slapd/rootdse.c | |
download | ds-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.c | 331 |
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 */ +} |