Back to index

openldap  2.4.31
root_dse.c
Go to the documentation of this file.
00001 /* root_dse.c - Provides the Root DSA-Specific Entry */
00002 /* $OpenLDAP$ */
00003 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
00004  *
00005  * Copyright 1999-2012 The OpenLDAP Foundation.
00006  * All rights reserved.
00007  *
00008  * Redistribution and use in source and binary forms, with or without
00009  * modification, are permitted only as authorized by the OpenLDAP
00010  * Public License.
00011  *
00012  * A copy of this license is available in the file LICENSE in the
00013  * top-level directory of the distribution or, alternatively, at
00014  * <http://www.OpenLDAP.org/license.html>.
00015  */
00016 
00017 #include "portable.h"
00018 
00019 #include <stdio.h>
00020 
00021 #include <ac/string.h>
00022 
00023 #include "slap.h"
00024 #include <ldif.h>
00025 #include "lber_pvt.h"
00026 
00027 #ifdef LDAP_SLAPI
00028 #include "slapi/slapi.h"
00029 #endif
00030 
00031 static struct berval builtin_supportedFeatures[] = {
00032        BER_BVC(LDAP_FEATURE_MODIFY_INCREMENT),          /* Modify/increment */
00033        BER_BVC(LDAP_FEATURE_ALL_OP_ATTRS),              /* All Op Attrs (+) */
00034        BER_BVC(LDAP_FEATURE_OBJECTCLASS_ATTRS),  /* OCs in Attrs List (@class) */
00035        BER_BVC(LDAP_FEATURE_ABSOLUTE_FILTERS),          /* (&) and (|) search filters */
00036        BER_BVC(LDAP_FEATURE_LANGUAGE_TAG_OPTIONS),      /* Language Tag Options */
00037        BER_BVC(LDAP_FEATURE_LANGUAGE_RANGE_OPTIONS),    /* Language Range Options */
00038 #ifdef LDAP_DEVEL
00039        BER_BVC(LDAP_FEATURE_SUBORDINATE_SCOPE),  /* "children" search scope */
00040 #endif
00041        BER_BVNULL
00042 };
00043 static struct berval *supportedFeatures;
00044 
00045 static Entry  *usr_attr = NULL;
00046 
00047 /*
00048  * allow modules to register functions that muck with the root DSE entry
00049  */
00050 
00051 typedef struct entry_info_t {
00052        SLAP_ENTRY_INFO_FN   func;
00053        void                 *arg;
00054        struct entry_info_t  *next;
00055 } entry_info_t;
00056 
00057 static entry_info_t *extra_info;
00058 
00059 int
00060 entry_info_register( SLAP_ENTRY_INFO_FN func, void *arg )
00061 {
00062        entry_info_t  *ei = ch_calloc( 1, sizeof( entry_info_t ) );
00063 
00064        ei->func = func;
00065        ei->arg = arg;
00066 
00067        ei->next = extra_info;
00068        extra_info = ei;
00069 
00070        return 0;
00071 }
00072 
00073 int
00074 entry_info_unregister( SLAP_ENTRY_INFO_FN func, void *arg )
00075 {
00076        entry_info_t  **eip;
00077 
00078        for ( eip = &extra_info; *eip != NULL; eip = &(*eip)->next ) {
00079               if ( (*eip)->func == func && (*eip)->arg == arg ) {
00080                      entry_info_t  *ei = *eip;
00081 
00082                      *eip = ei->next;
00083 
00084                      ch_free( ei );
00085 
00086                      return 0;
00087               }
00088        }
00089 
00090        return -1;
00091 }
00092 
00093 void
00094 entry_info_destroy( void )
00095 {
00096        entry_info_t  **eip;
00097 
00098        for ( eip = &extra_info; *eip != NULL;  ) {
00099               entry_info_t  *ei = *eip;
00100 
00101               eip = &(*eip)->next;
00102 
00103               ch_free( ei );
00104        }
00105 }
00106 
00107 /*
00108  * Allow modules to register supported features
00109  */
00110 
00111 static int
00112 supported_feature_init( void )
00113 {
00114        int           i;
00115 
00116        if ( supportedFeatures != NULL ) {
00117               return 0;
00118        }
00119 
00120        for ( i = 0; !BER_BVISNULL( &builtin_supportedFeatures[ i ] ); i++ )
00121               ;
00122 
00123        supportedFeatures = ch_calloc( sizeof( struct berval ), i + 1 );
00124        if ( supportedFeatures == NULL ) {
00125               return -1;
00126        }
00127 
00128        for ( i = 0; !BER_BVISNULL( &builtin_supportedFeatures[ i ] ); i++ ) {
00129               ber_dupbv( &supportedFeatures[ i ], &builtin_supportedFeatures[ i ] );
00130        }
00131        BER_BVZERO( &supportedFeatures[ i ] );
00132 
00133        return 0;
00134 }
00135 
00136 int
00137 supported_feature_destroy( void )
00138 {
00139        int           i;
00140 
00141        if ( supportedFeatures == NULL ) {
00142               return 0;
00143        }
00144        
00145        for ( i = 0; !BER_BVISNULL( &supportedFeatures[ i ] ); i++ ) {
00146               ch_free( supportedFeatures[ i ].bv_val );
00147        }
00148 
00149        ch_free( supportedFeatures );
00150        supportedFeatures = NULL;
00151 
00152        return 0;
00153 }
00154 
00155 int
00156 supported_feature_load( struct berval *f )
00157 {
00158        struct berval *tmp;
00159        int           i;
00160 
00161        supported_feature_init();
00162 
00163        for ( i = 0; !BER_BVISNULL( &supportedFeatures[ i ] ); i++ )
00164               ;
00165 
00166        tmp = ch_realloc( supportedFeatures, sizeof( struct berval ) * ( i + 2 ) );
00167        if ( tmp == NULL ) {
00168               return -1;
00169        }
00170        supportedFeatures = tmp;
00171 
00172        ber_dupbv( &supportedFeatures[ i ], f );
00173        BER_BVZERO( &supportedFeatures[ i + 1 ] );
00174 
00175        return 0;
00176 }
00177 
00178 int
00179 root_dse_info(
00180        Connection *conn,
00181        Entry **entry,
00182        const char **text )
00183 {
00184        Entry         *e;
00185        struct berval val;
00186 #ifdef LDAP_SLAPI
00187        struct berval *bv;
00188 #endif
00189        int           i, j;
00190        char ** supportedSASLMechanisms;
00191        BackendDB *be;
00192 
00193        AttributeDescription *ad_structuralObjectClass
00194               = slap_schema.si_ad_structuralObjectClass;
00195        AttributeDescription *ad_objectClass
00196               = slap_schema.si_ad_objectClass;
00197        AttributeDescription *ad_namingContexts
00198               = slap_schema.si_ad_namingContexts;
00199 #ifdef LDAP_SLAPI
00200        AttributeDescription *ad_supportedExtension
00201               = slap_schema.si_ad_supportedExtension;
00202 #endif
00203        AttributeDescription *ad_supportedLDAPVersion
00204               = slap_schema.si_ad_supportedLDAPVersion;
00205        AttributeDescription *ad_supportedSASLMechanisms
00206               = slap_schema.si_ad_supportedSASLMechanisms;
00207        AttributeDescription *ad_supportedFeatures
00208               = slap_schema.si_ad_supportedFeatures;
00209        AttributeDescription *ad_monitorContext
00210               = slap_schema.si_ad_monitorContext;
00211        AttributeDescription *ad_configContext
00212               = slap_schema.si_ad_configContext;
00213        AttributeDescription *ad_ref
00214               = slap_schema.si_ad_ref;
00215 
00216        e = entry_alloc();
00217        if( e == NULL ) {
00218               Debug( LDAP_DEBUG_ANY,
00219                      "root_dse_info: entry_alloc failed", 0, 0, 0 );
00220               return LDAP_OTHER;
00221        }
00222 
00223        e->e_attrs = NULL;
00224        e->e_name.bv_val = ch_strdup( LDAP_ROOT_DSE );
00225        e->e_name.bv_len = sizeof( LDAP_ROOT_DSE )-1;
00226        e->e_nname.bv_val = ch_strdup( LDAP_ROOT_DSE );
00227        e->e_nname.bv_len = sizeof( LDAP_ROOT_DSE )-1;
00228 
00229        /* the DN is an empty string so no pretty/normalization is needed */
00230        assert( !e->e_name.bv_len );
00231        assert( !e->e_nname.bv_len );
00232 
00233        e->e_private = NULL;
00234 
00235        /* FIXME: is this really needed? */
00236        BER_BVSTR( &val, "top" );
00237        if( attr_merge_one( e, ad_objectClass, &val, NULL ) ) {
00238 fail:
00239               entry_free( e );
00240               return LDAP_OTHER;
00241        }
00242 
00243        BER_BVSTR( &val, "OpenLDAProotDSE" );
00244        if( attr_merge_one( e, ad_objectClass, &val, NULL ) ) {
00245               goto fail;
00246        }
00247        if( attr_merge_one( e, ad_structuralObjectClass, &val, NULL ) ) {
00248               goto fail;
00249        }
00250 
00251        LDAP_STAILQ_FOREACH( be, &backendDB, be_next ) {
00252               if ( be->be_suffix == NULL
00253                             || be->be_nsuffix == NULL ) {
00254                      /* no suffix! */
00255                      continue;
00256               }
00257               if ( SLAP_MONITOR( be )) {
00258                      if( attr_merge_one( e, ad_monitorContext,
00259                                    &be->be_suffix[0],
00260                                    &be->be_nsuffix[0] ) )
00261                      {
00262                             goto fail;
00263                      }
00264                      continue;
00265               }
00266               if ( SLAP_CONFIG( be )) {
00267                      if( attr_merge_one( e, ad_configContext,
00268                                    &be->be_suffix[0],
00269                                    & be->be_nsuffix[0] ) )
00270                      {
00271                             goto fail;
00272                      }
00273                      continue;
00274               }
00275               if ( SLAP_GLUE_SUBORDINATE( be ) && !SLAP_GLUE_ADVERTISE( be ) ) {
00276                      continue;
00277               }
00278               for ( j = 0; be->be_suffix[j].bv_val != NULL; j++ ) {
00279                      if( attr_merge_one( e, ad_namingContexts,
00280                                    &be->be_suffix[j], NULL ) )
00281                      {
00282                             goto fail;
00283                      }
00284               }
00285        }
00286 
00287        /* altServer unsupported */
00288 
00289        /* supportedControl */
00290        if ( controls_root_dse_info( e ) != 0 ) {
00291               goto fail;
00292        }
00293 
00294        /* supportedExtension */
00295        if ( exop_root_dse_info( e ) != 0 ) {
00296               goto fail;
00297        }
00298 
00299 #ifdef LDAP_SLAPI
00300        /* netscape supportedExtension */
00301        for ( i = 0; (bv = slapi_int_get_supported_extop(i)) != NULL; i++ ) {
00302               if( attr_merge_one( e, ad_supportedExtension, bv, NULL ) ) {
00303                      goto fail;
00304               }
00305        }
00306 #endif /* LDAP_SLAPI */
00307 
00308        /* supportedFeatures */
00309        if ( supportedFeatures == NULL ) {
00310               supported_feature_init();
00311        }
00312 
00313        if( attr_merge( e, ad_supportedFeatures, supportedFeatures, NULL ) ) {
00314               goto fail;
00315        }
00316 
00317        /* supportedLDAPVersion */
00318               /* don't publish version 2 as we don't really support it
00319                * (even when configured to accept version 2 Bind requests)
00320                * and the value would never be used by true LDAPv2 (or LDAPv3)
00321                * clients.
00322                */
00323        for ( i=LDAP_VERSION3; i<=LDAP_VERSION_MAX; i++ ) {
00324               char buf[sizeof("255")];
00325               snprintf(buf, sizeof buf, "%d", i);
00326               val.bv_val = buf;
00327               val.bv_len = strlen( val.bv_val );
00328               if( attr_merge_one( e, ad_supportedLDAPVersion, &val, NULL ) ) {
00329                      goto fail;
00330               }
00331        }
00332 
00333        /* supportedSASLMechanism */
00334        supportedSASLMechanisms = slap_sasl_mechs( conn );
00335 
00336        if( supportedSASLMechanisms != NULL ) {
00337               for ( i=0; supportedSASLMechanisms[i] != NULL; i++ ) {
00338                      val.bv_val = supportedSASLMechanisms[i];
00339                      val.bv_len = strlen( val.bv_val );
00340                      if( attr_merge_one( e, ad_supportedSASLMechanisms, &val, NULL ) ) {
00341                             ldap_charray_free( supportedSASLMechanisms );
00342                             goto fail;
00343                      }
00344               }
00345               ldap_charray_free( supportedSASLMechanisms );
00346        }
00347 
00348        if ( default_referral != NULL ) {
00349               if( attr_merge( e, ad_ref, default_referral, NULL /* FIXME */ ) ) {
00350                      goto fail;
00351               }
00352        }
00353 
00354        if( usr_attr != NULL) {
00355               Attribute *a;
00356               for( a = usr_attr->e_attrs; a != NULL; a = a->a_next ) {
00357                      if( attr_merge( e, a->a_desc, a->a_vals,
00358                             (a->a_nvals == a->a_vals) ? NULL : a->a_nvals ) )
00359                      {
00360                             goto fail;
00361                      }
00362               }
00363        }
00364 
00365        if ( extra_info ) {
00366               entry_info_t  *ei = extra_info;
00367 
00368               for ( ; ei; ei = ei->next ) {
00369                      ei->func( ei->arg, e );
00370               }
00371        }
00372 
00373        *entry = e;
00374        return LDAP_SUCCESS;
00375 }
00376 
00377 int
00378 root_dse_init( void )
00379 {
00380        return 0;
00381 }
00382 
00383 int
00384 root_dse_destroy( void )
00385 {
00386        if ( usr_attr ) {
00387               entry_free( usr_attr );
00388               usr_attr = NULL;
00389        }
00390 
00391        return 0;
00392 }
00393 
00394 /*
00395  * Read the entries specified in fname and merge the attributes
00396  * to the user defined rootDSE. Note thaat if we find any errors
00397  * what so ever, we will discard the entire entries, print an
00398  * error message and return.
00399  */
00400 int
00401 root_dse_read_file( const char *fname )
00402 {
00403        struct LDIFFP *fp;
00404        int rc = 0, lineno = 0, lmax = 0, ldifrc;
00405        char   *buf = NULL;
00406 
00407        if ( (fp = ldif_open( fname, "r" )) == NULL ) {
00408               Debug( LDAP_DEBUG_ANY,
00409                      "root_dse_read_file: could not open rootdse attr file \"%s\" - absolute path?\n",
00410                      fname, 0, 0 );
00411               perror( fname );
00412               return EXIT_FAILURE;
00413        }
00414 
00415        usr_attr = entry_alloc();
00416        if( usr_attr == NULL ) {
00417               Debug( LDAP_DEBUG_ANY,
00418                      "root_dse_read_file: entry_alloc failed", 0, 0, 0 );
00419               ldif_close( fp );
00420               return LDAP_OTHER;
00421        }
00422        usr_attr->e_attrs = NULL;
00423 
00424        while(( ldifrc = ldif_read_record( fp, &lineno, &buf, &lmax )) > 0 ) {
00425               Entry *e = str2entry( buf );
00426               Attribute *a;
00427 
00428               if( e == NULL ) {
00429                      Debug( LDAP_DEBUG_ANY, "root_dse_read_file: "
00430                             "could not parse entry (file=\"%s\" line=%d)\n",
00431                             fname, lineno, 0 );
00432                      rc = LDAP_OTHER;
00433                      break;
00434               }
00435 
00436               /* make sure the DN is the empty DN */
00437               if( e->e_nname.bv_len ) {
00438                      Debug( LDAP_DEBUG_ANY,
00439                             "root_dse_read_file: invalid rootDSE "
00440                             "- dn=\"%s\" (file=\"%s\" line=%d)\n",
00441                             e->e_dn, fname, lineno );
00442                      entry_free( e );
00443                      rc = LDAP_OTHER;
00444                      break;
00445               }
00446 
00447               /*
00448                * we found a valid entry, so walk thru all the attributes in the
00449                * entry, and add each attribute type and description to the
00450                * usr_attr entry
00451                */
00452 
00453               for(a = e->e_attrs; a != NULL; a = a->a_next) {
00454                      if( attr_merge( usr_attr, a->a_desc, a->a_vals,
00455                             (a->a_nvals == a->a_vals) ? NULL : a->a_nvals ) )
00456                      {
00457                             rc = LDAP_OTHER;
00458                             break;
00459                      }
00460               }
00461 
00462               entry_free( e );
00463               if (rc) break;
00464        }
00465 
00466        if ( ldifrc < 0 )
00467               rc = LDAP_OTHER;
00468 
00469        if (rc) {
00470               entry_free( usr_attr );
00471               usr_attr = NULL;
00472        }
00473 
00474        ch_free( buf );
00475 
00476        ldif_close( fp );
00477 
00478        Debug(LDAP_DEBUG_CONFIG, "rootDSE file=\"%s\" read.\n", fname, 0, 0);
00479        return rc;
00480 }
00481 
00482 int
00483 slap_discover_feature(
00484        slap_bindconf *sb,
00485        const char    *attr,
00486        const char    *val )
00487 {
00488        LDAP          *ld = NULL;
00489        LDAPMessage   *res = NULL, *entry;
00490        int           rc, i;
00491        struct berval bv_val,
00492                      **values = NULL;
00493        char          *attrs[ 2 ] = { NULL, NULL };
00494 
00495        rc = slap_client_connect( &ld, sb );
00496        if ( rc != LDAP_SUCCESS ) {
00497               goto done;
00498        }
00499 
00500        attrs[ 0 ] = (char *) attr;
00501        rc = ldap_search_ext_s( ld, "", LDAP_SCOPE_BASE, "(objectClass=*)",
00502                      attrs, 0, NULL, NULL, NULL, 0, &res );
00503        if ( rc != LDAP_SUCCESS ) {
00504               goto done;
00505        }
00506 
00507        entry = ldap_first_entry( ld, res );
00508        if ( entry == NULL ) {
00509               goto done;
00510        }
00511 
00512        values = ldap_get_values_len( ld, entry, attrs[ 0 ] );
00513        if ( values == NULL ) {
00514               rc = LDAP_NO_SUCH_ATTRIBUTE;
00515               goto done;
00516        }
00517 
00518        ber_str2bv( val, 0, 0, &bv_val );
00519        for ( i = 0; values[ i ] != NULL; i++ ) {
00520               if ( bvmatch( &bv_val, values[ i ] ) ) {
00521                      rc = LDAP_COMPARE_TRUE;
00522                      goto done;
00523               }
00524        }
00525 
00526        rc = LDAP_COMPARE_FALSE;
00527 
00528 done:;
00529        if ( values != NULL ) {
00530               ldap_value_free_len( values );
00531        }
00532 
00533        if ( res != NULL ) {
00534               ldap_msgfree( res );
00535        }
00536 
00537        ldap_unbind_ext( ld, NULL, NULL );
00538 
00539        return rc;
00540 }
00541