/* * call from within ldap_back_db_open() */ int ldap_back_monitor_db_open( BackendDB *be ) { ldapinfo_t *li = (ldapinfo_t *) be->be_private; char buf[ BACKMONITOR_BUFSIZE ]; Entry *e = NULL; monitor_callback_t *cb = NULL; struct berval suffix, *filter, *base; char *ptr; time_t now; char timebuf[ LDAP_LUTIL_GENTIME_BUFSIZE ]; struct berval timestamp; int rc = 0; BackendInfo *mi; monitor_extra_t *mbe; if ( !SLAP_DBMONITORING( be ) ) { return 0; } /* check if monitor is configured and usable */ mi = backend_info( "monitor" ); if ( !mi || !mi->bi_extra ) { SLAP_DBFLAGS( be ) ^= SLAP_DBFLAG_MONITORING; return 0; } mbe = mi->bi_extra; /* don't bother if monitor is not configured */ if ( !mbe->is_configured() ) { static int warning = 0; if ( warning++ == 0 ) { Debug( LDAP_DEBUG_ANY, "ldap_back_monitor_db_open: " "monitoring disabled; " "configure monitor database to enable\n", 0, 0, 0 ); } return 0; } /* set up the fake subsystem that is used to create * the volatile connection entries */ li->li_monitor_info.lmi_mss.mss_name = "back-ldap"; li->li_monitor_info.lmi_mss.mss_flags = MONITOR_F_VOLATILE_CH; li->li_monitor_info.lmi_mss.mss_create = ldap_back_monitor_conn_create; li->li_monitor_info.lmi_li = li; li->li_monitor_info.lmi_scope = LDAP_SCOPE_SUBORDINATE; base = &li->li_monitor_info.lmi_base; BER_BVSTR( base, "cn=databases,cn=monitor" ); filter = &li->li_monitor_info.lmi_filter; BER_BVZERO( filter ); suffix.bv_len = ldap_bv2escaped_filter_value_len( &be->be_nsuffix[ 0 ] ); if ( suffix.bv_len == be->be_nsuffix[ 0 ].bv_len ) { suffix = be->be_nsuffix[ 0 ]; } else { ldap_bv2escaped_filter_value( &be->be_nsuffix[ 0 ], &suffix ); } filter->bv_len = STRLENOF( "(&" ) + li->li_monitor_info.lmi_more_filter.bv_len + STRLENOF( "(monitoredInfo=" ) + strlen( be->bd_info->bi_type ) + STRLENOF( ")(!(monitorOverlay=" ) + strlen( be->bd_info->bi_type ) + STRLENOF( "))(namingContexts:distinguishedNameMatch:=" ) + suffix.bv_len + STRLENOF( "))" ); ptr = filter->bv_val = ch_malloc( filter->bv_len + 1 ); ptr = lutil_strcopy( ptr, "(&" ); ptr = lutil_strncopy( ptr, li->li_monitor_info.lmi_more_filter.bv_val, li->li_monitor_info.lmi_more_filter.bv_len ); ptr = lutil_strcopy( ptr, "(monitoredInfo=" ); ptr = lutil_strcopy( ptr, be->bd_info->bi_type ); ptr = lutil_strcopy( ptr, ")(!(monitorOverlay=" ); ptr = lutil_strcopy( ptr, be->bd_info->bi_type ); ptr = lutil_strcopy( ptr, "))(namingContexts:distinguishedNameMatch:=" ); ptr = lutil_strncopy( ptr, suffix.bv_val, suffix.bv_len ); ptr = lutil_strcopy( ptr, "))" ); ptr[ 0 ] = '\0'; assert( ptr == &filter->bv_val[ filter->bv_len ] ); if ( suffix.bv_val != be->be_nsuffix[ 0 ].bv_val ) { ch_free( suffix.bv_val ); } now = slap_get_time(); timestamp.bv_val = timebuf; timestamp.bv_len = sizeof( timebuf ); slap_timestamp( &now, ×tamp ); /* caller (e.g. an overlay based on back-ldap) may want to use * a different RDN... */ if ( BER_BVISNULL( &li->li_monitor_info.lmi_rdn ) ) { ber_str2bv( "cn=Connections", 0, 1, &li->li_monitor_info.lmi_rdn ); } ptr = ber_bvchr( &li->li_monitor_info.lmi_rdn, '=' ); assert( ptr != NULL ); ptr[ 0 ] = '\0'; ptr++; snprintf( buf, sizeof( buf ), "dn: %s=%s\n" "objectClass: monitorContainer\n" "%s: %s\n" "creatorsName: %s\n" "createTimestamp: %s\n" "modifiersName: %s\n" "modifyTimestamp: %s\n", li->li_monitor_info.lmi_rdn.bv_val, ptr, li->li_monitor_info.lmi_rdn.bv_val, ptr, BER_BVISNULL( &be->be_rootdn ) ? SLAPD_ANONYMOUS : be->be_rootdn.bv_val, timestamp.bv_val, BER_BVISNULL( &be->be_rootdn ) ? SLAPD_ANONYMOUS : be->be_rootdn.bv_val, timestamp.bv_val ); e = str2entry( buf ); if ( e == NULL ) { rc = -1; goto cleanup; } ptr[ -1 ] = '='; /* add labeledURI and special, modifiable URI value */ if ( li->li_uri != NULL ) { struct berval bv; LDAPURLDesc *ludlist = NULL; int rc; rc = ldap_url_parselist_ext( &ludlist, li->li_uri, NULL, LDAP_PVT_URL_PARSE_NOEMPTY_HOST | LDAP_PVT_URL_PARSE_DEF_PORT ); if ( rc != LDAP_URL_SUCCESS ) { Debug( LDAP_DEBUG_ANY, "ldap_back_monitor_db_open: " "unable to parse URI list (ignored)\n", 0, 0, 0 ); } else { for ( ; ludlist != NULL; ) { LDAPURLDesc *next = ludlist->lud_next; bv.bv_val = ldap_url_desc2str( ludlist ); assert( bv.bv_val != NULL ); ldap_free_urldesc( ludlist ); bv.bv_len = strlen( bv.bv_val ); attr_merge_normalize_one( e, slap_schema.si_ad_labeledURI, &bv, NULL ); ch_free( bv.bv_val ); ludlist = next; } } ber_str2bv( li->li_uri, 0, 0, &bv ); attr_merge_normalize_one( e, ad_olmDbURIList, &bv, NULL ); } ber_dupbv( &li->li_monitor_info.lmi_nrdn, &e->e_nname ); cb = ch_calloc( sizeof( monitor_callback_t ), 1 ); cb->mc_update = ldap_back_monitor_update; cb->mc_modify = ldap_back_monitor_modify; cb->mc_free = ldap_back_monitor_free; cb->mc_private = (void *)li; rc = mbe->register_entry_parent( e, cb, (monitor_subsys_t *)&li->li_monitor_info, MONITOR_F_VOLATILE_CH, base, LDAP_SCOPE_SUBORDINATE, filter ); cleanup:; if ( rc != 0 ) { if ( cb != NULL ) { ch_free( cb ); cb = NULL; } if ( e != NULL ) { entry_free( e ); e = NULL; } if ( !BER_BVISNULL( filter ) ) { ch_free( filter->bv_val ); BER_BVZERO( filter ); } } /* store for cleanup */ li->li_monitor_info.lmi_cb = (void *)cb; if ( e != NULL ) { entry_free( e ); } return rc; }
int ldap_set_option( LDAP *ld, int option, LDAP_CONST void *invalue) { struct ldapoptions *lo; int *dbglvl = NULL; int rc = LDAP_OPT_ERROR; /* Get pointer to global option structure */ lo = LDAP_INT_GLOBAL_OPT(); if (lo == NULL) { return LDAP_NO_MEMORY; } /* * The architecture to turn on debugging has a chicken and egg * problem. Thus, we introduce a fix here. */ if (option == LDAP_OPT_DEBUG_LEVEL) { dbglvl = (int *) invalue; } if( lo->ldo_valid != LDAP_INITIALIZED ) { ldap_int_initialize(lo, dbglvl); if ( lo->ldo_valid != LDAP_INITIALIZED ) return LDAP_LOCAL_ERROR; } if(ld != NULL) { assert( LDAP_VALID( ld ) ); if( !LDAP_VALID( ld ) ) { return LDAP_OPT_ERROR; } lo = &ld->ld_options; } LDAP_MUTEX_LOCK( &lo->ldo_mutex ); switch ( option ) { /* options with boolean values */ case LDAP_OPT_REFERRALS: if(invalue == LDAP_OPT_OFF) { LDAP_BOOL_CLR(lo, LDAP_BOOL_REFERRALS); } else { LDAP_BOOL_SET(lo, LDAP_BOOL_REFERRALS); } rc = LDAP_OPT_SUCCESS; break; case LDAP_OPT_RESTART: if(invalue == LDAP_OPT_OFF) { LDAP_BOOL_CLR(lo, LDAP_BOOL_RESTART); } else { LDAP_BOOL_SET(lo, LDAP_BOOL_RESTART); } rc = LDAP_OPT_SUCCESS; break; case LDAP_OPT_CONNECT_ASYNC: if(invalue == LDAP_OPT_OFF) { LDAP_BOOL_CLR(lo, LDAP_BOOL_CONNECT_ASYNC); } else { LDAP_BOOL_SET(lo, LDAP_BOOL_CONNECT_ASYNC); } rc = LDAP_OPT_SUCCESS; break; /* options which can withstand invalue == NULL */ case LDAP_OPT_SERVER_CONTROLS: { LDAPControl *const *controls = (LDAPControl *const *) invalue; if( lo->ldo_sctrls ) ldap_controls_free( lo->ldo_sctrls ); if( controls == NULL || *controls == NULL ) { lo->ldo_sctrls = NULL; rc = LDAP_OPT_SUCCESS; break; } lo->ldo_sctrls = ldap_controls_dup( controls ); if(lo->ldo_sctrls == NULL) { /* memory allocation error ? */ break; /* LDAP_OPT_ERROR */ } } rc = LDAP_OPT_SUCCESS; break; case LDAP_OPT_CLIENT_CONTROLS: { LDAPControl *const *controls = (LDAPControl *const *) invalue; if( lo->ldo_cctrls ) ldap_controls_free( lo->ldo_cctrls ); if( controls == NULL || *controls == NULL ) { lo->ldo_cctrls = NULL; rc = LDAP_OPT_SUCCESS; break; } lo->ldo_cctrls = ldap_controls_dup( controls ); if(lo->ldo_cctrls == NULL) { /* memory allocation error ? */ break; /* LDAP_OPT_ERROR */ } } rc = LDAP_OPT_SUCCESS; break; case LDAP_OPT_HOST_NAME: { const char *host = (const char *) invalue; LDAPURLDesc *ludlist = NULL; rc = LDAP_OPT_SUCCESS; if(host != NULL) { rc = ldap_url_parsehosts( &ludlist, host, lo->ldo_defport ? lo->ldo_defport : LDAP_PORT ); } else if(ld == NULL) { /* * must want global default returned * to initial condition. */ rc = ldap_url_parselist_ext(&ludlist, "ldap://localhost/", NULL, LDAP_PVT_URL_PARSE_NOEMPTY_HOST | LDAP_PVT_URL_PARSE_DEF_PORT ); } else { /* * must want the session default * updated to the current global default */ ludlist = ldap_url_duplist( ldap_int_global_options.ldo_defludp); if (ludlist == NULL) rc = LDAP_NO_MEMORY; } if (rc == LDAP_OPT_SUCCESS) { if (lo->ldo_defludp != NULL) ldap_free_urllist(lo->ldo_defludp); lo->ldo_defludp = ludlist; } break; } case LDAP_OPT_URI: { const char *urls = (const char *) invalue; LDAPURLDesc *ludlist = NULL; rc = LDAP_OPT_SUCCESS; if(urls != NULL) { rc = ldap_url_parselist_ext(&ludlist, urls, NULL, LDAP_PVT_URL_PARSE_NOEMPTY_HOST | LDAP_PVT_URL_PARSE_DEF_PORT ); } else if(ld == NULL) { /* * must want global default returned * to initial condition. */ rc = ldap_url_parselist_ext(&ludlist, "ldap://localhost/", NULL, LDAP_PVT_URL_PARSE_NOEMPTY_HOST | LDAP_PVT_URL_PARSE_DEF_PORT ); } else { /* * must want the session default * updated to the current global default */ ludlist = ldap_url_duplist( ldap_int_global_options.ldo_defludp); if (ludlist == NULL) rc = LDAP_URL_ERR_MEM; } switch (rc) { case LDAP_URL_SUCCESS: /* Success */ rc = LDAP_SUCCESS; break; case LDAP_URL_ERR_MEM: /* can't allocate memory space */ rc = LDAP_NO_MEMORY; break; case LDAP_URL_ERR_PARAM: /* parameter is bad */ case LDAP_URL_ERR_BADSCHEME: /* URL doesn't begin with "ldap[si]://" */ case LDAP_URL_ERR_BADENCLOSURE: /* URL is missing trailing ">" */ case LDAP_URL_ERR_BADURL: /* URL is bad */ case LDAP_URL_ERR_BADHOST: /* host port is bad */ case LDAP_URL_ERR_BADATTRS: /* bad (or missing) attributes */ case LDAP_URL_ERR_BADSCOPE: /* scope string is invalid (or missing) */ case LDAP_URL_ERR_BADFILTER: /* bad or missing filter */ case LDAP_URL_ERR_BADEXTS: /* bad or missing extensions */ rc = LDAP_PARAM_ERROR; break; } if (rc == LDAP_SUCCESS) { if (lo->ldo_defludp != NULL) ldap_free_urllist(lo->ldo_defludp); lo->ldo_defludp = ludlist; } break; } case LDAP_OPT_DEFBASE: { const char *newbase = (const char *) invalue; char *defbase = NULL; if ( newbase != NULL ) { defbase = LDAP_STRDUP( newbase ); if ( defbase == NULL ) { rc = LDAP_NO_MEMORY; break; } } else if ( ld != NULL ) { defbase = LDAP_STRDUP( ldap_int_global_options.ldo_defbase ); if ( defbase == NULL ) { rc = LDAP_NO_MEMORY; break; } } if ( lo->ldo_defbase != NULL ) LDAP_FREE( lo->ldo_defbase ); lo->ldo_defbase = defbase; } rc = LDAP_OPT_SUCCESS; break; case LDAP_OPT_DIAGNOSTIC_MESSAGE: { const char *err = (const char *) invalue; if(ld == NULL) { /* need a struct ldap */ break; /* LDAP_OPT_ERROR */ } if( ld->ld_error ) { LDAP_FREE(ld->ld_error); ld->ld_error = NULL; } if ( err ) { ld->ld_error = LDAP_STRDUP(err); } } rc = LDAP_OPT_SUCCESS; break; case LDAP_OPT_MATCHED_DN: { const char *matched = (const char *) invalue; if (ld == NULL) { /* need a struct ldap */ break; /* LDAP_OPT_ERROR */ } if( ld->ld_matched ) { LDAP_FREE(ld->ld_matched); ld->ld_matched = NULL; } if ( matched ) { ld->ld_matched = LDAP_STRDUP( matched ); } } rc = LDAP_OPT_SUCCESS; break; case LDAP_OPT_REFERRAL_URLS: { char *const *referrals = (char *const *) invalue; if(ld == NULL) { /* need a struct ldap */ break; /* LDAP_OPT_ERROR */ } if( ld->ld_referrals ) { LDAP_VFREE(ld->ld_referrals); } if ( referrals ) { ld->ld_referrals = ldap_value_dup(referrals); } } rc = LDAP_OPT_SUCCESS; break; /* Only accessed from inside this function by ldap_set_rebind_proc() */ case LDAP_OPT_REBIND_PROC: { lo->ldo_rebind_proc = (LDAP_REBIND_PROC *)invalue; } rc = LDAP_OPT_SUCCESS; break; case LDAP_OPT_REBIND_PARAMS: { lo->ldo_rebind_params = (void *)invalue; } rc = LDAP_OPT_SUCCESS; break; /* Only accessed from inside this function by ldap_set_nextref_proc() */ case LDAP_OPT_NEXTREF_PROC: { lo->ldo_nextref_proc = (LDAP_NEXTREF_PROC *)invalue; } rc = LDAP_OPT_SUCCESS; break; case LDAP_OPT_NEXTREF_PARAMS: { lo->ldo_nextref_params = (void *)invalue; } rc = LDAP_OPT_SUCCESS; break; /* Only accessed from inside this function by ldap_set_urllist_proc() */ case LDAP_OPT_URLLIST_PROC: { lo->ldo_urllist_proc = (LDAP_URLLIST_PROC *)invalue; } rc = LDAP_OPT_SUCCESS; break; case LDAP_OPT_URLLIST_PARAMS: { lo->ldo_urllist_params = (void *)invalue; } rc = LDAP_OPT_SUCCESS; break; /* read-only options */ case LDAP_OPT_API_INFO: case LDAP_OPT_DESC: case LDAP_OPT_SOCKBUF: case LDAP_OPT_API_FEATURE_INFO: break; /* LDAP_OPT_ERROR */ /* options which cannot withstand invalue == NULL */ case LDAP_OPT_DEREF: case LDAP_OPT_SIZELIMIT: case LDAP_OPT_TIMELIMIT: case LDAP_OPT_PROTOCOL_VERSION: case LDAP_OPT_RESULT_CODE: case LDAP_OPT_DEBUG_LEVEL: case LDAP_OPT_TIMEOUT: case LDAP_OPT_NETWORK_TIMEOUT: case LDAP_OPT_CONNECT_CB: case LDAP_OPT_X_KEEPALIVE_IDLE: case LDAP_OPT_X_KEEPALIVE_PROBES : case LDAP_OPT_X_KEEPALIVE_INTERVAL : if(invalue == NULL) { /* no place to set from */ LDAP_MUTEX_UNLOCK( &lo->ldo_mutex ); return ( LDAP_OPT_ERROR ); } break; default: #ifdef HAVE_TLS if ( ldap_pvt_tls_set_option( ld, option, (void *)invalue ) == 0 ) { LDAP_MUTEX_UNLOCK( &lo->ldo_mutex ); return ( LDAP_OPT_SUCCESS ); } #endif #ifdef HAVE_CYRUS_SASL if ( ldap_int_sasl_set_option( ld, option, (void *)invalue ) == 0 ) { LDAP_MUTEX_UNLOCK( &lo->ldo_mutex ); return ( LDAP_OPT_SUCCESS ); } #endif #ifdef HAVE_GSSAPI if ( ldap_int_gssapi_set_option( ld, option, (void *)invalue ) == 0 ) { LDAP_MUTEX_UNLOCK( &lo->ldo_mutex ); return ( LDAP_OPT_SUCCESS ); } #endif /* bad param */ break; /* LDAP_OPT_ERROR */ } /* options which cannot withstand invalue == NULL */ switch(option) { case LDAP_OPT_DEREF: /* FIXME: check value for protocol compliance? */ lo->ldo_deref = * (const int *) invalue; rc = LDAP_OPT_SUCCESS; break; case LDAP_OPT_SIZELIMIT: /* FIXME: check value for protocol compliance? */ lo->ldo_sizelimit = * (const int *) invalue; rc = LDAP_OPT_SUCCESS; break; case LDAP_OPT_TIMELIMIT: /* FIXME: check value for protocol compliance? */ lo->ldo_timelimit = * (const int *) invalue; rc = LDAP_OPT_SUCCESS; break; case LDAP_OPT_TIMEOUT: { const struct timeval *tv = (const struct timeval *) invalue; lo->ldo_tm_api = *tv; } rc = LDAP_OPT_SUCCESS; break; case LDAP_OPT_NETWORK_TIMEOUT: { const struct timeval *tv = (const struct timeval *) invalue; lo->ldo_tm_net = *tv; } rc = LDAP_OPT_SUCCESS; break; case LDAP_OPT_PROTOCOL_VERSION: { int vers = * (const int *) invalue; if (vers < LDAP_VERSION_MIN || vers > LDAP_VERSION_MAX) { /* not supported */ break; } lo->ldo_version = vers; } rc = LDAP_OPT_SUCCESS; break; case LDAP_OPT_RESULT_CODE: { int err = * (const int *) invalue; if(ld == NULL) { /* need a struct ldap */ break; } ld->ld_errno = err; } rc = LDAP_OPT_SUCCESS; break; case LDAP_OPT_DEBUG_LEVEL: lo->ldo_debug = * (const int *) invalue; rc = LDAP_OPT_SUCCESS; break; case LDAP_OPT_CONNECT_CB: { /* setting pushes the callback */ ldaplist *ll; ll = LDAP_MALLOC( sizeof( *ll )); ll->ll_data = (void *)invalue; ll->ll_next = lo->ldo_conn_cbs; lo->ldo_conn_cbs = ll; } rc = LDAP_OPT_SUCCESS; break; case LDAP_OPT_X_KEEPALIVE_IDLE: lo->ldo_keepalive_idle = * (const int *) invalue; rc = LDAP_OPT_SUCCESS; break; case LDAP_OPT_X_KEEPALIVE_PROBES : lo->ldo_keepalive_probes = * (const int *) invalue; rc = LDAP_OPT_SUCCESS; break; case LDAP_OPT_X_KEEPALIVE_INTERVAL : lo->ldo_keepalive_interval = * (const int *) invalue; rc = LDAP_OPT_SUCCESS; break; } LDAP_MUTEX_UNLOCK( &lo->ldo_mutex ); return ( rc ); }
static int ldap_back_monitor_modify( Operation *op, SlapReply *rs, Entry *e, void *priv ) { ldapinfo_t *li = (ldapinfo_t *) priv; Attribute *save_attrs = NULL; Modifications *ml, *ml_olmDbURIList = NULL; struct berval ul = BER_BVNULL; int got = 0; for ( ml = op->orm_modlist; ml; ml = ml->sml_next ) { if ( ml->sml_desc == ad_olmDbURIList ) { if ( ml_olmDbURIList != NULL ) { rs->sr_err = LDAP_CONSTRAINT_VIOLATION; rs->sr_text = "conflicting modifications"; goto done; } if ( ml->sml_op != LDAP_MOD_REPLACE ) { rs->sr_err = LDAP_CONSTRAINT_VIOLATION; rs->sr_text = "modification not allowed"; goto done; } ml_olmDbURIList = ml; got++; continue; } } if ( got == 0 ) { return SLAP_CB_CONTINUE; } save_attrs = attrs_dup( e->e_attrs ); if ( ml_olmDbURIList != NULL ) { Attribute *a = NULL; LDAPURLDesc *ludlist = NULL; int rc; ml = ml_olmDbURIList; assert( ml->sml_nvalues != NULL ); if ( BER_BVISNULL( &ml->sml_nvalues[ 0 ] ) ) { rs->sr_err = LDAP_CONSTRAINT_VIOLATION; rs->sr_text = "no value provided"; goto done; } if ( !BER_BVISNULL( &ml->sml_nvalues[ 1 ] ) ) { rs->sr_err = LDAP_CONSTRAINT_VIOLATION; rs->sr_text = "multiple values provided"; goto done; } rc = ldap_url_parselist_ext( &ludlist, ml->sml_nvalues[ 0 ].bv_val, NULL, LDAP_PVT_URL_PARSE_NOEMPTY_HOST | LDAP_PVT_URL_PARSE_DEF_PORT ); if ( rc != LDAP_URL_SUCCESS ) { rs->sr_err = LDAP_INVALID_SYNTAX; rs->sr_text = "unable to parse URI list"; goto done; } ul.bv_val = ldap_url_list2urls( ludlist ); ldap_free_urllist( ludlist ); if ( ul.bv_val == NULL ) { rs->sr_err = LDAP_OTHER; goto done; } ul.bv_len = strlen( ul.bv_val ); a = attr_find( e->e_attrs, ad_olmDbURIList ); if ( a != NULL ) { if ( a->a_nvals == a->a_vals ) { a->a_nvals = ch_calloc( sizeof( struct berval ), 2 ); } ber_bvreplace( &a->a_vals[ 0 ], &ul ); ber_bvreplace( &a->a_nvals[ 0 ], &ul ); } else { attr_merge_normalize_one( e, ad_olmDbURIList, &ul, NULL ); } } /* apply changes */ if ( !BER_BVISNULL( &ul ) ) { ldap_pvt_thread_mutex_lock( &li->li_uri_mutex ); if ( li->li_uri ) { ch_free( li->li_uri ); } li->li_uri = ul.bv_val; ldap_pvt_thread_mutex_unlock( &li->li_uri_mutex ); BER_BVZERO( &ul ); } done:; if ( !BER_BVISNULL( &ul ) ) { ldap_memfree( ul.bv_val ); } if ( rs->sr_err == LDAP_SUCCESS ) { attrs_free( save_attrs ); return SLAP_CB_CONTINUE; } attrs_free( e->e_attrs ); e->e_attrs = save_attrs; return rs->sr_err; }