void slap_sl_mem_destroy( void *key, void *data ) { struct slab_heap *sh = data; int pad = 2*sizeof(int)-1, pad_shift; int order_start = -1, i; struct slab_object *so; if (sh->sh_stack) { ber_memfree_x(sh->sh_base, NULL); ber_memfree_x(sh, NULL); } else { pad_shift = pad - 1; do { order_start++; } while (pad_shift >>= 1); for (i = 0; i <= sh->sh_maxorder - order_start; i++) { so = LDAP_LIST_FIRST(&sh->sh_free[i]); while (so) { struct slab_object *so_tmp = so; so = LDAP_LIST_NEXT(so, so_link); LDAP_LIST_INSERT_HEAD(&sh->sh_sopool, so_tmp, so_link); } ch_free(sh->sh_map[i]); } ch_free(sh->sh_free); ch_free(sh->sh_map); so = LDAP_LIST_FIRST(&sh->sh_sopool); while (so) { struct slab_object *so_tmp = so; so = LDAP_LIST_NEXT(so, so_link); if (!so_tmp->so_blockhead) { LDAP_LIST_REMOVE(so_tmp, so_link); } } so = LDAP_LIST_FIRST(&sh->sh_sopool); while (so) { struct slab_object *so_tmp = so; so = LDAP_LIST_NEXT(so, so_link); ch_free(so_tmp); } ber_memfree_x(sh->sh_base, NULL); ber_memfree_x(sh, NULL); } }
RETCODE backsql_FreeRow_x( BACKSQL_ROW_NTS *row, void *ctx ) { if ( row->cols == NULL ) { return SQL_ERROR; } ber_bvarray_free_x( row->col_names, ctx ); ber_memfree_x( row->col_prec, ctx ); ber_memfree_x( row->col_type, ctx ); ber_memvfree_x( (void **)row->cols, ctx ); ber_memfree_x( row->value_len, ctx ); return SQL_SUCCESS; }
void anlist_free( AttributeName *an, int freename, void *ctx ) { if ( an == NULL ) { return; } if ( freename ) { int i; for ( i = 0; an[i].an_name.bv_val; i++ ) { ber_memfree_x( an[i].an_name.bv_val, ctx ); } } ber_memfree_x( an, ctx ); }
static void scope_chunk_free( void *key, void *data ) { ID2 *p1, *p2; for (p1 = data; p1; p1 = p2) { p2 = p1[0].mval.mv_data; ber_memfree_x(p1, NULL); } }
void slap_op_free( Operation *op, void *ctx ) { OperationBuffer *opbuf; assert( LDAP_STAILQ_NEXT(op, o_next) == NULL ); if ( op->o_ber != NULL ) { ber_free( op->o_ber, 1 ); } if ( !BER_BVISNULL( &op->o_dn ) ) { ch_free( op->o_dn.bv_val ); } if ( !BER_BVISNULL( &op->o_ndn ) ) { ch_free( op->o_ndn.bv_val ); } if ( !BER_BVISNULL( &op->o_authmech ) ) { ch_free( op->o_authmech.bv_val ); } if ( op->o_ctrls != NULL ) { slap_free_ctrls( op, op->o_ctrls ); } #ifdef LDAP_CONNECTIONLESS if ( op->o_res_ber != NULL ) { ber_free( op->o_res_ber, 1 ); } #endif if ( op->o_groups ) { slap_op_groups_free( op ); } #if defined( LDAP_SLAPI ) if ( slapi_plugins_used ) { slapi_int_free_object_extensions( SLAPI_X_EXT_OPERATION, op ); } #endif /* defined( LDAP_SLAPI ) */ if ( !BER_BVISNULL( &op->o_csn ) ) { op->o_tmpfree( op->o_csn.bv_val, op->o_tmpmemctx ); BER_BVZERO( &op->o_csn ); } opbuf = (OperationBuffer *) op; memset( opbuf, 0, sizeof(*opbuf) ); op->o_hdr = &opbuf->ob_hdr; op->o_controls = opbuf->ob_controls; if ( ctx ) { void *op2 = NULL; ldap_pvt_thread_pool_setkey( ctx, (void *)slap_op_free, op, slap_op_q_destroy, &op2, NULL ); LDAP_STAILQ_NEXT( op, o_next ) = op2; } else { ber_memfree_x( op, NULL ); } }
void ber_free_buf( BerElement *ber ) { Seqorset *s, *next; assert( LBER_VALID( ber ) ); if ( ber->ber_buf) ber_memfree_x( ber->ber_buf, ber->ber_memctx ); for( s = ber->ber_sos ; s != NULL ; s = next ) { next = s->sos_next; ber_memfree_x( s, ber->ber_memctx ); } ber->ber_buf = NULL; ber->ber_sos = NULL; ber->ber_valid = LBER_UNINITIALIZED; }
static void slap_op_q_destroy( void *key, void *data ) { Operation *op, *op2; for ( op = data; op; op = op2 ) { op2 = LDAP_STAILQ_NEXT( op, o_next ); ber_memfree_x( op, NULL ); } }
/* Destroy the context, or if key==NULL clean it up for reuse. */ void slap_sl_mem_destroy( void *key, void *data ) { struct slab_heap *sh = data; struct slab_object *so; int i; if (!sh->sh_stack) { for (i = 0; i <= sh->sh_maxorder - order_start; i++) { so = LDAP_LIST_FIRST(&sh->sh_free[i]); while (so) { struct slab_object *so_tmp = so; so = LDAP_LIST_NEXT(so, so_link); LDAP_LIST_INSERT_HEAD(&sh->sh_sopool, so_tmp, so_link); } ch_free(sh->sh_map[i]); } ch_free(sh->sh_free); ch_free(sh->sh_map); so = LDAP_LIST_FIRST(&sh->sh_sopool); while (so) { struct slab_object *so_tmp = so; so = LDAP_LIST_NEXT(so, so_link); if (!so_tmp->so_blockhead) { LDAP_LIST_REMOVE(so_tmp, so_link); } } so = LDAP_LIST_FIRST(&sh->sh_sopool); while (so) { struct slab_object *so_tmp = so; so = LDAP_LIST_NEXT(so, so_link); ch_free(so_tmp); } } if (key != NULL) { ber_memfree_x(sh->sh_base, NULL); ber_memfree_x(sh, NULL); } }
static int retcode_op_internal( Operation *op, SlapReply *rs ) { slap_overinst *on = (slap_overinst *)op->o_bd->bd_info; Operation op2 = *op; BackendDB db = *op->o_bd; slap_callback sc = { 0 }; retcode_cb_t rdc; int rc; op2.o_tag = LDAP_REQ_SEARCH; op2.ors_scope = LDAP_SCOPE_BASE; op2.ors_deref = LDAP_DEREF_NEVER; op2.ors_tlimit = SLAP_NO_LIMIT; op2.ors_slimit = SLAP_NO_LIMIT; op2.ors_limit = NULL; op2.ors_attrsonly = 0; op2.ors_attrs = slap_anlist_all_attributes; ber_str2bv_x( "(objectClass=errAbsObject)", STRLENOF( "(objectClass=errAbsObject)" ), 1, &op2.ors_filterstr, op2.o_tmpmemctx ); op2.ors_filter = str2filter_x( &op2, op2.ors_filterstr.bv_val ); /* errAbsObject is defined by this overlay! */ assert( op2.ors_filter != NULL ); db.bd_info = on->on_info->oi_orig; op2.o_bd = &db; rdc.rdc_info = on->on_info->oi_orig; rdc.rdc_flags = RETCODE_FINDIR; if ( op->o_tag == LDAP_REQ_SEARCH ) { rdc.rdc_attrs = op->ors_attrs; } rdc.rdc_tag = op->o_tag; sc.sc_response = retcode_cb_response; sc.sc_private = &rdc; op2.o_callback = ≻ rc = op2.o_bd->be_search( &op2, rs ); op->o_abandon = op2.o_abandon; filter_free_x( &op2, op2.ors_filter, 1 ); ber_memfree_x( op2.ors_filterstr.bv_val, op2.o_tmpmemctx ); if ( rdc.rdc_flags == SLAP_CB_CONTINUE ) { return SLAP_CB_CONTINUE; } return rc; }
void ber_free_buf( BerElement *ber ) { assert( LBER_VALID( ber ) ); if ( ber->ber_buf) ber_memfree_x( ber->ber_buf, ber->ber_memctx ); ber->ber_buf = NULL; ber->ber_sos_ptr = NULL; ber->ber_valid = LBER_UNINITIALIZED; }
static int OpenLDAPaciNormalizeRights( struct berval *actions, struct berval *nactions, void *ctx ) { struct berval bv = BER_BVNULL; int i; BER_BVZERO( nactions ); for ( i = 0; acl_get_part( actions, i, '$', &bv ) >= 0; i++ ) { int rc; struct berval nbv; rc = OpenLDAPaciNormalizeRight( &bv, &nbv, ctx ); if ( rc != LDAP_SUCCESS ) { ber_memfree_x( nactions->bv_val, ctx ); BER_BVZERO( nactions ); return LDAP_INVALID_SYNTAX; } if ( i == 0 ) { *nactions = nbv; } else { nactions->bv_val = ber_memrealloc_x( nactions->bv_val, nactions->bv_len + STRLENOF( "$" ) + nbv.bv_len + 1, ctx ); nactions->bv_val[ nactions->bv_len ] = '$'; memcpy( &nactions->bv_val[ nactions->bv_len + 1 ], nbv.bv_val, nbv.bv_len + 1 ); ber_memfree_x( nbv.bv_val, ctx ); nactions->bv_len += STRLENOF( "$" ) + nbv.bv_len; } BER_BVZERO( &nbv ); } return LDAP_SUCCESS; }
void ber_free( BerElement *ber, int freebuf ) { if( ber == NULL ) { LDAP_MEMORY_DEBUG_ASSERT( ber != NULL ); return; } if( freebuf ) ber_free_buf( ber ); ber_memfree_x( (char *) ber, ber->ber_memctx ); }
void ldap_ldif_record_done( LDIFRecord *lr ) { int i; /* the LDAPControl stuff does not allow the use of memory contexts */ if (lr->lr_ctrls != NULL) { ldap_controls_free( lr->lr_ctrls ); } if ( lr->lr_lm != NULL ) { ber_memfree_x( lr->lr_lm, lr->lr_ctx ); } if ( lr->lr_mops != NULL ) { ber_memfree_x( lr->lr_mops, lr->lr_ctx ); } for (i=lr->lr_lines-1; i>=0; i--) if ( lr->lr_freeval[i] ) ber_memfree_x( lr->lr_vals[i].bv_val, lr->lr_ctx ); ber_memfree_x( lr->lr_btype, lr->lr_ctx ); memset( lr, 0, sizeof(LDIFRecord) ); }
static int monitor_subsys_rww_destroy( BackendDB *be, monitor_subsys_t *ms ) { int i; for ( i = 0; i < MONITOR_RWW_LAST; i++ ) { ber_memfree_x( monitor_rww[ i ].nrdn.bv_val, NULL ); } return 0; }
/* * meta_clear_one_candidate * * clears the selected candidate */ int meta_clear_one_candidate( Operation *op, metaconn_t *mc, int candidate ) { metasingleconn_t *msc = &mc->mc_conns[ candidate ]; if ( msc->msc_ld != NULL ) { #ifdef DEBUG_205 char buf[ BUFSIZ ]; snprintf( buf, sizeof( buf ), "meta_clear_one_candidate ldap_unbind_ext[%d] mc=%p ld=%p", candidate, (void *)mc, (void *)msc->msc_ld ); Debug( LDAP_DEBUG_ANY, "### %s %s\n", op ? op->o_log_prefix : "", buf, 0 ); #endif /* DEBUG_205 */ ldap_unbind_ext( msc->msc_ld, NULL, NULL ); msc->msc_ld = NULL; } if ( !BER_BVISNULL( &msc->msc_bound_ndn ) ) { ber_memfree_x( msc->msc_bound_ndn.bv_val, NULL ); BER_BVZERO( &msc->msc_bound_ndn ); } if ( !BER_BVISNULL( &msc->msc_cred ) ) { memset( msc->msc_cred.bv_val, 0, msc->msc_cred.bv_len ); ber_memfree_x( msc->msc_cred.bv_val, NULL ); BER_BVZERO( &msc->msc_cred ); } msc->msc_mscflags = 0; return 0; }
static int OpenLDAPaciNormalizeRight( struct berval *action, struct berval *naction, void *ctx ) { struct berval grantdeny, perms = BER_BVNULL, bv = BER_BVNULL; int idx, i; /* grant|deny */ if ( acl_get_part( action, 0, ';', &grantdeny ) < 0 ) { Debug( LDAP_DEBUG_ACL, "aciNormalizeRight: missing ';' in '%s'\n", action->bv_val ); return LDAP_INVALID_SYNTAX; } idx = bv_getcaseidx( &grantdeny, ACIgrantdeny ); if ( idx == -1 ) { Debug( LDAP_DEBUG_ACL, "aciNormalizeRight: '%s' must be grant or deny\n", grantdeny.bv_val ); return LDAP_INVALID_SYNTAX; } ber_dupbv_x( naction, (struct berval *)ACIgrantdeny[ idx ], ctx ); for ( i = 1; acl_get_part( action, i, ';', &bv ) >= 0; i++ ) { struct berval nattrs = BER_BVNULL; int freenattrs = 1; if ( i & 1 ) { /* perms */ if ( OpenLDAPaciValidatePerms( &bv ) != LDAP_SUCCESS ) { return LDAP_INVALID_SYNTAX; } perms = bv; } else { /* attr */ char *ptr; /* could be "[all]" or an attribute description */ if ( ber_bvstrcasecmp( &bv, &aci_bv[ ACI_BV_BR_ALL ] ) == 0 ) { nattrs = aci_bv[ ACI_BV_BR_ALL ]; freenattrs = 0; } else { AttributeDescription *ad = NULL; AttributeDescription adstatic= { 0 }; const char *text = NULL; struct berval attr, left, right; int j; int len; for ( j = 0; acl_get_part( &bv, j, ',', &attr ) >= 0; j++ ) { ad = NULL; text = NULL; /* openldap 2.1 aci compabitibility [entry] -> entry */ if ( ber_bvstrcasecmp( &attr, &aci_bv[ ACI_BV_BR_ENTRY ] ) == 0 ) { ad = &adstatic; adstatic.ad_cname = aci_bv[ ACI_BV_ENTRY ]; /* openldap 2.1 aci compabitibility [children] -> children */ } else if ( ber_bvstrcasecmp( &attr, &aci_bv[ ACI_BV_BR_CHILDREN ] ) == 0 ) { ad = &adstatic; adstatic.ad_cname = aci_bv[ ACI_BV_CHILDREN ]; /* openldap 2.1 aci compabitibility [all] -> only [all] */ } else if ( ber_bvstrcasecmp( &attr, &aci_bv[ ACI_BV_BR_ALL ] ) == 0 ) { ber_memfree_x( nattrs.bv_val, ctx ); nattrs = aci_bv[ ACI_BV_BR_ALL ]; freenattrs = 0; break; } else if ( acl_get_part( &attr, 0, '=', &left ) < 0 || acl_get_part( &attr, 1, '=', &right ) < 0 ) { if ( slap_bv2ad( &attr, &ad, &text ) != LDAP_SUCCESS ) { ber_memfree_x( nattrs.bv_val, ctx ); Debug( LDAP_DEBUG_ACL, "aciNormalizeRight: unknown attribute: '%s'\n", attr.bv_val ); return LDAP_INVALID_SYNTAX; } } else { if ( slap_bv2ad( &left, &ad, &text ) != LDAP_SUCCESS ) { ber_memfree_x( nattrs.bv_val, ctx ); Debug( LDAP_DEBUG_ACL, "aciNormalizeRight: unknown attribute: '%s'\n", left.bv_val ); return LDAP_INVALID_SYNTAX; } } len = nattrs.bv_len + ( !BER_BVISEMPTY( &nattrs ) ? STRLENOF( "," ) : 0 ) + ad->ad_cname.bv_len; nattrs.bv_val = ber_memrealloc_x( nattrs.bv_val, len + 1, ctx ); ptr = &nattrs.bv_val[ nattrs.bv_len ]; if ( !BER_BVISEMPTY( &nattrs ) ) { *ptr++ = ','; } ptr = lutil_strncopy( ptr, ad->ad_cname.bv_val, ad->ad_cname.bv_len ); ptr[ 0 ] = '\0'; nattrs.bv_len = len; } } naction->bv_val = ber_memrealloc_x( naction->bv_val, naction->bv_len + STRLENOF( ";" ) + perms.bv_len + STRLENOF( ";" ) + nattrs.bv_len + 1, ctx ); ptr = &naction->bv_val[ naction->bv_len ]; ptr[ 0 ] = ';'; ptr++; ptr = lutil_strncopy( ptr, perms.bv_val, perms.bv_len ); ptr[ 0 ] = ';'; ptr++; ptr = lutil_strncopy( ptr, nattrs.bv_val, nattrs.bv_len ); ptr[ 0 ] = '\0'; naction->bv_len += STRLENOF( ";" ) + perms.bv_len + STRLENOF( ";" ) + nattrs.bv_len; if ( freenattrs ) { ber_memfree_x( nattrs.bv_val, ctx ); } } } /* perms;attr go in pairs */ if ( i > 1 && ( i & 1 ) ) { return LDAP_SUCCESS; } else { Debug( LDAP_DEBUG_ACL, "aciNormalizeRight: perms:attr need to be pairs in '%s'\n", action->bv_val ); return LDAP_INVALID_SYNTAX; } }
static void search_stack_free( void *key, void *data ) { ber_memfree_x(data, NULL); }
int asyncmeta_handle_search_msg(LDAPMessage *res, a_metaconn_t *mc, bm_context_t *bc, int candidate) { a_metainfo_t *mi; a_metatarget_t *mt; a_metasingleconn_t *msc; Operation *op = bc->op; SlapReply *rs; int i, rc = LDAP_SUCCESS, sres; SlapReply *candidates; char **references = NULL; LDAPControl **ctrls = NULL; a_dncookie dc; LDAPMessage *msg; ber_int_t id; rs = &bc->rs; mi = mc->mc_info; mt = mi->mi_targets[ candidate ]; msc = &mc->mc_conns[ candidate ]; dc.op = op; dc.target = mt; dc.to_from = MASSAGE_REP; id = ldap_msgid(res); candidates = bc->candidates; i = candidate; while (res && !META_BACK_CONN_INVALID(msc)) { for (msg = ldap_first_message(msc->msc_ldr, res); msg; msg = ldap_next_message(msc->msc_ldr, msg)) { switch(ldap_msgtype(msg)) { case LDAP_RES_SEARCH_ENTRY: Debug( LDAP_DEBUG_TRACE, "%s asyncmeta_handle_search_msg: msc %p entry\n", op->o_log_prefix, msc ); if ( candidates[ i ].sr_type == REP_INTERMEDIATE ) { /* don't retry any more... */ candidates[ i ].sr_type = REP_RESULT; } /* count entries returned by target */ candidates[ i ].sr_nentries++; if (bc->c_peer_name.bv_val == op->o_conn->c_peer_name.bv_val && !op->o_abandon) { rs->sr_err = asyncmeta_send_entry( &bc->copy_op, rs, mc, i, msg ); } else { goto err_cleanup; } switch ( rs->sr_err ) { case LDAP_SIZELIMIT_EXCEEDED: asyncmeta_send_ldap_result(bc, op, rs); rs->sr_err = LDAP_SUCCESS; goto err_cleanup; case LDAP_UNAVAILABLE: rs->sr_err = LDAP_OTHER; break; default: break; } bc->is_ok++; break; case LDAP_RES_SEARCH_REFERENCE: if ( META_BACK_TGT_NOREFS( mt ) ) { rs->sr_err = LDAP_OTHER; asyncmeta_send_ldap_result(bc, op, rs); goto err_cleanup; } if ( candidates[ i ].sr_type == REP_INTERMEDIATE ) { /* don't retry any more... */ candidates[ i ].sr_type = REP_RESULT; } bc->is_ok++; rc = ldap_parse_reference( msc->msc_ldr, msg, &references, &rs->sr_ctrls, 0 ); if ( rc != LDAP_SUCCESS || references == NULL ) { rs->sr_err = LDAP_OTHER; asyncmeta_send_ldap_result(bc, op, rs); goto err_cleanup; } /* FIXME: merge all and return at the end */ { int cnt; for ( cnt = 0; references[ cnt ]; cnt++ ) ; rs->sr_ref = ber_memalloc_x( sizeof( struct berval ) * ( cnt + 1 ), op->o_tmpmemctx ); for ( cnt = 0; references[ cnt ]; cnt++ ) { ber_str2bv_x( references[ cnt ], 0, 1, &rs->sr_ref[ cnt ], op->o_tmpmemctx ); } BER_BVZERO( &rs->sr_ref[ cnt ] ); } { dc.memctx = op->o_tmpmemctx; ( void )asyncmeta_referral_result_rewrite( &dc, rs->sr_ref ); } if ( rs->sr_ref != NULL ) { if (!BER_BVISNULL( &rs->sr_ref[ 0 ] ) ) { /* ignore return value by now */ ( void )send_search_reference( op, rs ); } ber_bvarray_free_x( rs->sr_ref, op->o_tmpmemctx ); rs->sr_ref = NULL; } /* cleanup */ if ( references ) { ber_memvfree( (void **)references ); } if ( rs->sr_ctrls ) { ldap_controls_free( rs->sr_ctrls ); rs->sr_ctrls = NULL; } break; case LDAP_RES_INTERMEDIATE: if ( candidates[ i ].sr_type == REP_INTERMEDIATE ) { /* don't retry any more... */ candidates[ i ].sr_type = REP_RESULT; } bc->is_ok++; /* FIXME: response controls * are passed without checks */ rs->sr_err = ldap_parse_intermediate( msc->msc_ldr, msg, (char **)&rs->sr_rspoid, &rs->sr_rspdata, &rs->sr_ctrls, 0 ); if ( rs->sr_err != LDAP_SUCCESS ) { candidates[ i ].sr_type = REP_RESULT; rs->sr_err = LDAP_OTHER; asyncmeta_send_ldap_result(bc, op, rs); goto err_cleanup; } slap_send_ldap_intermediate( op, rs ); if ( rs->sr_rspoid != NULL ) { ber_memfree( (char *)rs->sr_rspoid ); rs->sr_rspoid = NULL; } if ( rs->sr_rspdata != NULL ) { ber_bvfree( rs->sr_rspdata ); rs->sr_rspdata = NULL; } if ( rs->sr_ctrls != NULL ) { ldap_controls_free( rs->sr_ctrls ); rs->sr_ctrls = NULL; } break; case LDAP_RES_SEARCH_RESULT: if ( mi->mi_idle_timeout != 0 ) { asyncmeta_set_msc_time(msc); } Debug( LDAP_DEBUG_TRACE, "%s asyncmeta_handle_search_msg: msc %p result\n", op->o_log_prefix, msc ); candidates[ i ].sr_type = REP_RESULT; candidates[ i ].sr_msgid = META_MSGID_IGNORE; /* NOTE: ignores response controls * (and intermediate response controls * as well, except for those with search * references); this may not be correct, * but if they're not ignored then * back-meta would need to merge them * consistently (think of pagedResults...) */ /* FIXME: response controls? */ rs->sr_err = ldap_parse_result( msc->msc_ldr, msg, &candidates[ i ].sr_err, (char **)&candidates[ i ].sr_matched, (char **)&candidates[ i ].sr_text, &references, &ctrls /* &candidates[ i ].sr_ctrls (unused) */ , 0 ); if ( rs->sr_err != LDAP_SUCCESS ) { candidates[ i ].sr_err = rs->sr_err; sres = slap_map_api2result( &candidates[ i ] ); candidates[ i ].sr_type = REP_RESULT; goto finish; } rs->sr_err = candidates[ i ].sr_err; /* massage matchedDN if need be */ if ( candidates[ i ].sr_matched != NULL ) { struct berval match, mmatch; ber_str2bv( candidates[ i ].sr_matched, 0, 0, &match ); candidates[ i ].sr_matched = NULL; dc.memctx = NULL; asyncmeta_dn_massage( &dc, &match, &mmatch ); if ( mmatch.bv_val == match.bv_val ) { candidates[ i ].sr_matched = ch_strdup( mmatch.bv_val ); } else { candidates[ i ].sr_matched = mmatch.bv_val; } bc->candidate_match++; ldap_memfree( match.bv_val ); } /* add references to array */ /* RFC 4511: referrals can only appear * if result code is LDAP_REFERRAL */ if ( references != NULL && references[ 0 ] != NULL && references[ 0 ][ 0 ] != '\0' ) { if ( rs->sr_err != LDAP_REFERRAL ) { Debug( LDAP_DEBUG_ANY, "%s asncmeta_search_result[%d]: " "got referrals with err=%d\n", op->o_log_prefix, i, rs->sr_err ); } else { BerVarray sr_ref; int cnt; for ( cnt = 0; references[ cnt ]; cnt++ ) ; sr_ref = ber_memalloc_x( sizeof( struct berval ) * ( cnt + 1 ), op->o_tmpmemctx ); for ( cnt = 0; references[ cnt ]; cnt++ ) { ber_str2bv_x( references[ cnt ], 0, 1, &sr_ref[ cnt ], op->o_tmpmemctx ); } BER_BVZERO( &sr_ref[ cnt ] ); dc.memctx = op->o_tmpmemctx; ( void )asyncmeta_referral_result_rewrite( &dc, sr_ref ); if ( rs->sr_v2ref == NULL ) { rs->sr_v2ref = sr_ref; } else { for ( cnt = 0; !BER_BVISNULL( &sr_ref[ cnt ] ); cnt++ ) { ber_bvarray_add_x( &rs->sr_v2ref, &sr_ref[ cnt ], op->o_tmpmemctx ); } ber_memfree_x( sr_ref, op->o_tmpmemctx ); } } } else if ( rs->sr_err == LDAP_REFERRAL ) { Debug( LDAP_DEBUG_TRACE, "%s asyncmeta_search_result[%d]: " "got err=%d with null " "or empty referrals\n", op->o_log_prefix, i, rs->sr_err ); rs->sr_err = LDAP_NO_SUCH_OBJECT; } /* cleanup */ ber_memvfree( (void **)references ); sres = slap_map_api2result( rs ); if ( candidates[ i ].sr_err == LDAP_SUCCESS ) { Debug( LDAP_DEBUG_TRACE, "%s asyncmeta_search_result[%d] " "match=\"%s\" err=%ld", op->o_log_prefix, i, candidates[ i ].sr_matched ? candidates[ i ].sr_matched : "", (long) candidates[ i ].sr_err ); } else { Debug( LDAP_DEBUG_ANY, "%s asyncmeta_search_result[%d] " "match=\"%s\" err=%ld (%s)", op->o_log_prefix, i, candidates[ i ].sr_matched ? candidates[ i ].sr_matched : "", (long) candidates[ i ].sr_err, ldap_err2string( candidates[ i ].sr_err ) ); } switch ( sres ) { case LDAP_NO_SUCH_OBJECT: /* is_ok is touched any time a valid * (even intermediate) result is * returned; as a consequence, if * a candidate returns noSuchObject * it is ignored and the candidate * is simply demoted. */ if ( bc->is_ok ) { sres = LDAP_SUCCESS; } break; case LDAP_SUCCESS: if ( ctrls != NULL && ctrls[0] != NULL ) { #ifdef SLAPD_META_CLIENT_PR LDAPControl *pr_c; pr_c = ldap_control_find( LDAP_CONTROL_PAGEDRESULTS, ctrls, NULL ); if ( pr_c != NULL ) { BerElementBuffer berbuf; BerElement *ber = (BerElement *)&berbuf; ber_tag_t tag; ber_int_t prsize; struct berval prcookie; /* unsolicited, do not accept */ if ( mt->mt_ps == 0 ) { rs->sr_err = LDAP_OTHER; goto err_pr; } ber_init2( ber, &pr_c->ldctl_value, LBER_USE_DER ); tag = ber_scanf( ber, "{im}", &prsize, &prcookie ); if ( tag == LBER_ERROR ) { rs->sr_err = LDAP_OTHER; goto err_pr; } /* more pages? new search request */ if ( !BER_BVISNULL( &prcookie ) && !BER_BVISEMPTY( &prcookie ) ) { if ( mt->mt_ps > 0 ) { /* ignore size if specified */ prsize = 0; } else if ( prsize == 0 ) { /* guess the page size from the entries returned so far */ prsize = candidates[ i ].sr_nentries; } candidates[ i ].sr_nentries = 0; candidates[ i ].sr_msgid = META_MSGID_IGNORE; candidates[ i ].sr_type = REP_INTERMEDIATE; assert( candidates[ i ].sr_matched == NULL ); assert( candidates[ i ].sr_text == NULL ); assert( candidates[ i ].sr_ref == NULL ); switch ( asyncmeta_back_search_start( &bc->copy_op, rs, mc, bc, i, &prcookie, prsize, 1 ) ) { case META_SEARCH_CANDIDATE: assert( candidates[ i ].sr_msgid >= 0 ); ldap_controls_free( ctrls ); // goto free_message; case META_SEARCH_ERR: case META_SEARCH_NEED_BIND: err_pr:; candidates[ i ].sr_err = rs->sr_err; candidates[ i ].sr_type = REP_RESULT; if ( META_BACK_ONERR_STOP( mi ) ) { asyncmeta_send_ldap_result(bc, op, rs); ldap_controls_free( ctrls ); goto err_cleanup; } /* fallthru */ case META_SEARCH_NOT_CANDIDATE: /* means that asyncmeta_back_search_start() * failed but onerr == continue */ candidates[ i ].sr_msgid = META_MSGID_IGNORE; candidates[ i ].sr_type = REP_RESULT; break; default: /* impossible */ assert( 0 ); break; } break; } } #endif /* SLAPD_META_CLIENT_PR */ ldap_controls_free( ctrls ); } /* fallthru */ case LDAP_REFERRAL: bc->is_ok++; break; case LDAP_SIZELIMIT_EXCEEDED: /* if a target returned sizelimitExceeded * and the entry count is equal to the * proxy's limit, the target would have * returned more, and the error must be * propagated to the client; otherwise, * the target enforced a limit lower * than what requested by the proxy; * ignore it */ candidates[ i ].sr_err = rs->sr_err; if ( rs->sr_nentries == op->ors_slimit || META_BACK_ONERR_STOP( mi ) ) { const char *save_text; got_err: save_text = rs->sr_text; rs->sr_text = candidates[ i ].sr_text; asyncmeta_send_ldap_result(bc, op, rs); if (candidates[ i ].sr_text != NULL) { ch_free( (char *)candidates[ i ].sr_text ); candidates[ i ].sr_text = NULL; } rs->sr_text = save_text; ldap_controls_free( ctrls ); goto err_cleanup; } break; default: candidates[ i ].sr_err = rs->sr_err; if ( META_BACK_ONERR_STOP( mi ) ) { goto got_err; } break; } /* if this is the last result we will ever receive, send it back */ rc = rs->sr_err; if (asyncmeta_is_last_result(mc, bc, i) == 0) { Debug( LDAP_DEBUG_TRACE, "%s asyncmeta_handle_search_msg: msc %p last result\n", op->o_log_prefix, msc ); asyncmeta_search_last_result(mc, bc, i, sres); err_cleanup: rc = rs->sr_err; ldap_pvt_thread_mutex_lock( &mc->mc_om_mutex ); asyncmeta_drop_bc( mc, bc); asyncmeta_clear_bm_context(bc); ldap_pvt_thread_mutex_unlock( &mc->mc_om_mutex ); ldap_msgfree(res); return rc; } finish: break; default: continue; } } ldap_msgfree(res); res = NULL; if (candidates[ i ].sr_type != REP_RESULT) { struct timeval tv = {0}; rc = ldap_result( msc->msc_ldr, id, LDAP_MSG_RECEIVED, &tv, &res ); if (res != NULL) { msc->msc_result_time = slap_get_time(); } } } ldap_pvt_thread_mutex_lock( &mc->mc_om_mutex ); bc->bc_active--; ldap_pvt_thread_mutex_unlock( &mc->mc_om_mutex ); return rc; }
static int deref_parseCtrl ( Operation *op, SlapReply *rs, LDAPControl *ctrl ) { ber_tag_t tag; BerElementBuffer berbuf; BerElement *ber = (BerElement *)&berbuf; ber_len_t len; char *last; DerefSpec *dshead = NULL, **dsp = &dshead; BerVarray attributes = NULL; if ( op->o_deref != SLAP_CONTROL_NONE ) { rs->sr_text = "Dereference control specified multiple times"; return LDAP_PROTOCOL_ERROR; } if ( BER_BVISNULL( &ctrl->ldctl_value ) ) { rs->sr_text = "Dereference control value is absent"; return LDAP_PROTOCOL_ERROR; } if ( BER_BVISEMPTY( &ctrl->ldctl_value ) ) { rs->sr_text = "Dereference control value is empty"; return LDAP_PROTOCOL_ERROR; } ber_init2( ber, &ctrl->ldctl_value, 0 ); for ( tag = ber_first_element( ber, &len, &last ); tag != LBER_DEFAULT; tag = ber_next_element( ber, &len, last ) ) { struct berval derefAttr; DerefSpec *ds, *dstmp; const char *text; int rc; ber_len_t cnt = sizeof(struct berval); ber_len_t off = 0; if ( ber_scanf( ber, "{m{M}}", &derefAttr, &attributes, &cnt, off ) == LBER_ERROR || !cnt ) { rs->sr_text = "Dereference control: derefSpec decoding error"; rs->sr_err = LDAP_PROTOCOL_ERROR; goto done; } ds = (DerefSpec *)op->o_tmpcalloc( 1, sizeof(DerefSpec) + sizeof(AttributeDescription *)*(cnt + 1), op->o_tmpmemctx ); ds->ds_attributes = (AttributeDescription **)&ds[ 1 ]; ds->ds_nattrs = cnt; rc = slap_bv2ad( &derefAttr, &ds->ds_derefAttr, &text ); if ( rc != LDAP_SUCCESS ) { rs->sr_text = "Dereference control: derefAttr decoding error"; rs->sr_err = LDAP_PROTOCOL_ERROR; goto done; } for ( dstmp = dshead; dstmp && dstmp != ds; dstmp = dstmp->ds_next ) { if ( dstmp->ds_derefAttr == ds->ds_derefAttr ) { rs->sr_text = "Dereference control: derefAttr must be unique within control"; rs->sr_err = LDAP_PROTOCOL_ERROR; goto done; } } if ( !( ds->ds_derefAttr->ad_type->sat_syntax->ssyn_flags & SLAP_SYNTAX_DN )) { if ( ctrl->ldctl_iscritical ) { rs->sr_text = "Dereference control: derefAttr syntax not distinguishedName"; rs->sr_err = LDAP_PROTOCOL_ERROR; goto done; } rs->sr_err = LDAP_SUCCESS; goto justcleanup; } for ( cnt = 0; !BER_BVISNULL( &attributes[ cnt ] ); cnt++ ) { rc = slap_bv2ad( &attributes[ cnt ], &ds->ds_attributes[ cnt ], &text ); if ( rc != LDAP_SUCCESS ) { rs->sr_text = "Dereference control: attribute decoding error"; rs->sr_err = LDAP_PROTOCOL_ERROR; goto done; } } ber_memfree_x( attributes, op->o_tmpmemctx ); attributes = NULL; *dsp = ds; dsp = &ds->ds_next; } op->o_ctrlderef = (void *)dshead; op->o_deref = ctrl->ldctl_iscritical ? SLAP_CONTROL_CRITICAL : SLAP_CONTROL_NONCRITICAL; rs->sr_err = LDAP_SUCCESS; done:; if ( rs->sr_err != LDAP_SUCCESS ) { justcleanup:; for ( ; dshead; ) { DerefSpec *dsnext = dshead->ds_next; op->o_tmpfree( dshead, op->o_tmpmemctx ); dshead = dsnext; } } if ( attributes != NULL ) { ber_memfree_x( attributes, op->o_tmpmemctx ); } return rs->sr_err; }
int fe_op_modrdn( Operation *op, SlapReply *rs ) { struct berval dest_ndn = BER_BVNULL, dest_pndn, pdn = BER_BVNULL; BackendDB *op_be, *bd = op->o_bd; ber_slen_t diff; if( op->o_req_ndn.bv_len == 0 ) { Debug( LDAP_DEBUG_ANY, "%s do_modrdn: root dse!\n", op->o_log_prefix, 0, 0 ); send_ldap_error( op, rs, LDAP_UNWILLING_TO_PERFORM, "cannot rename the root DSE" ); goto cleanup; } else if ( bvmatch( &op->o_req_ndn, &frontendDB->be_schemandn ) ) { Debug( LDAP_DEBUG_ANY, "%s do_modrdn: subschema subentry: %s (%ld)\n", op->o_log_prefix, frontendDB->be_schemandn.bv_val, (long)frontendDB->be_schemandn.bv_len ); send_ldap_error( op, rs, LDAP_UNWILLING_TO_PERFORM, "cannot rename subschema subentry" ); goto cleanup; } if( op->orr_nnewSup ) { dest_pndn = *op->orr_nnewSup; } else { dnParent( &op->o_req_ndn, &dest_pndn ); } build_new_dn( &dest_ndn, &dest_pndn, &op->orr_nnewrdn, op->o_tmpmemctx ); diff = (ber_slen_t) dest_ndn.bv_len - (ber_slen_t) op->o_req_ndn.bv_len; if ( diff > 0 ? dnIsSuffix( &dest_ndn, &op->o_req_ndn ) : diff < 0 && dnIsSuffix( &op->o_req_ndn, &dest_ndn ) ) { send_ldap_error( op, rs, LDAP_UNWILLING_TO_PERFORM, diff > 0 ? "cannot place an entry below itself" : "cannot place an entry above itself" ); goto cleanup; } /* * We could be serving multiple database backends. Select the * appropriate one, or send a referral to our "referral server" * if we don't hold it. */ op->o_bd = select_backend( &op->o_req_ndn, 1 ); if ( op->o_bd == NULL ) { op->o_bd = bd; rs->sr_ref = referral_rewrite( default_referral, NULL, &op->o_req_dn, LDAP_SCOPE_DEFAULT ); if (!rs->sr_ref) rs->sr_ref = default_referral; if ( rs->sr_ref != NULL ) { rs->sr_err = LDAP_REFERRAL; send_ldap_result( op, rs ); if (rs->sr_ref != default_referral) ber_bvarray_free( rs->sr_ref ); } else { send_ldap_error( op, rs, LDAP_UNWILLING_TO_PERFORM, "no global superior knowledge" ); } goto cleanup; } /* If we've got a glued backend, check the real backend */ op_be = op->o_bd; if ( SLAP_GLUE_INSTANCE( op->o_bd )) { op->o_bd = select_backend( &op->o_req_ndn, 0 ); } /* check restrictions */ if( backend_check_restrictions( op, rs, NULL ) != LDAP_SUCCESS ) { send_ldap_result( op, rs ); goto cleanup; } /* check for referrals */ if ( backend_check_referrals( op, rs ) != LDAP_SUCCESS ) { goto cleanup; } /* check that destination DN is in the same backend as source DN */ if ( select_backend( &dest_ndn, 0 ) != op->o_bd ) { send_ldap_error( op, rs, LDAP_AFFECTS_MULTIPLE_DSAS, "cannot rename between DSAs" ); goto cleanup; } /* * do the modrdn if 1 && (2 || 3) * 1) there is a modrdn function implemented in this backend; * 2) this backend is master for what it holds; * 3) it's a replica and the dn supplied is the update_ndn. */ if ( op->o_bd->be_modrdn ) { /* do the update here */ int repl_user = be_isupdate( op ); if ( !SLAP_SINGLE_SHADOW(op->o_bd) || repl_user ) { op->o_bd = op_be; op->o_bd->be_modrdn( op, rs ); if ( op->o_bd->be_delete ) { struct berval org_req_dn = BER_BVNULL; struct berval org_req_ndn = BER_BVNULL; struct berval org_dn = BER_BVNULL; struct berval org_ndn = BER_BVNULL; int org_managedsait; org_req_dn = op->o_req_dn; org_req_ndn = op->o_req_ndn; org_dn = op->o_dn; org_ndn = op->o_ndn; org_managedsait = get_manageDSAit( op ); op->o_dn = op->o_bd->be_rootdn; op->o_ndn = op->o_bd->be_rootndn; op->o_managedsait = SLAP_CONTROL_NONCRITICAL; while ( rs->sr_err == LDAP_SUCCESS && op->o_delete_glue_parent ) { op->o_delete_glue_parent = 0; if ( !be_issuffix( op->o_bd, &op->o_req_ndn )) { slap_callback cb = { NULL }; cb.sc_response = slap_null_cb; dnParent( &op->o_req_ndn, &pdn ); op->o_req_dn = pdn; op->o_req_ndn = pdn; op->o_callback = &cb; op->o_bd->be_delete( op, rs ); } else { break; } } op->o_managedsait = org_managedsait; op->o_dn = org_dn; op->o_ndn = org_ndn; op->o_req_dn = org_req_dn; op->o_req_ndn = org_req_ndn; op->o_delete_glue_parent = 0; } } else { BerVarray defref = op->o_bd->be_update_refs ? op->o_bd->be_update_refs : default_referral; if ( defref != NULL ) { rs->sr_ref = referral_rewrite( defref, NULL, &op->o_req_dn, LDAP_SCOPE_DEFAULT ); if (!rs->sr_ref) rs->sr_ref = defref; rs->sr_err = LDAP_REFERRAL; send_ldap_result( op, rs ); if (rs->sr_ref != defref) ber_bvarray_free( rs->sr_ref ); } else { send_ldap_error( op, rs, LDAP_UNWILLING_TO_PERFORM, "shadow context; no update referral" ); } } } else { send_ldap_error( op, rs, LDAP_UNWILLING_TO_PERFORM, "operation not supported within namingContext" ); } cleanup:; if ( dest_ndn.bv_val != NULL ) ber_memfree_x( dest_ndn.bv_val, op->o_tmpmemctx ); op->o_bd = bd; return rs->sr_err; }
static int asyncmeta_send_entry( Operation *op, SlapReply *rs, a_metaconn_t *mc, int target, LDAPMessage *e ) { a_metainfo_t *mi = mc->mc_info; struct berval a, mapped = BER_BVNULL; int check_sorted_attrs = 0; Entry ent = {0}; BerElement ber = *ldap_get_message_ber( e ); Attribute *attr, **attrp; struct berval bdn, dn = BER_BVNULL; const char *text; a_dncookie dc; ber_len_t len; int rc; void *mem_mark; mem_mark = slap_sl_mark( op->o_tmpmemctx ); ber_set_option( &ber, LBER_OPT_BER_MEMCTX, &op->o_tmpmemctx ); if ( ber_scanf( &ber, "l{", &len ) == LBER_ERROR ) { return LDAP_DECODING_ERROR; } if ( ber_set_option( &ber, LBER_OPT_REMAINING_BYTES, &len ) != LBER_OPT_SUCCESS ) { return LDAP_OTHER; } if ( ber_scanf( &ber, "m{", &bdn ) == LBER_ERROR ) { return LDAP_DECODING_ERROR; } /* * Rewrite the dn of the result, if needed */ dc.op = op; dc.target = mi->mi_targets[ target ]; dc.memctx = op->o_tmpmemctx; dc.to_from = MASSAGE_REP; asyncmeta_dn_massage( &dc, &bdn, &dn ); /* * Note: this may fail if the target host(s) schema differs * from the one known to the meta, and a DN with unknown * attributes is returned. * * FIXME: should we log anything, or delegate to dnNormalize? */ rc = dnPrettyNormal( NULL, &dn, &ent.e_name, &ent.e_nname, op->o_tmpmemctx ); if ( dn.bv_val != bdn.bv_val ) { op->o_tmpfree( dn.bv_val, op->o_tmpmemctx ); } BER_BVZERO( &dn ); if ( rc != LDAP_SUCCESS ) { Debug( LDAP_DEBUG_ANY, "%s asyncmeta_send_entry(\"%s\"): " "invalid DN syntax\n", op->o_log_prefix, ent.e_name.bv_val ); rc = LDAP_INVALID_DN_SYNTAX; goto done; } /* * cache dn */ if ( mi->mi_cache.ttl != META_DNCACHE_DISABLED ) { ( void )asyncmeta_dncache_update_entry( &mi->mi_cache, &ent.e_nname, target ); } attrp = &ent.e_attrs; while ( ber_scanf( &ber, "{m", &a ) != LBER_ERROR ) { int last = 0; slap_syntax_validate_func *validate; slap_syntax_transform_func *pretty; if ( ber_pvt_ber_remaining( &ber ) < 0 ) { Debug( LDAP_DEBUG_ANY, "%s asyncmeta_send_entry(\"%s\"): " "unable to parse attr \"%s\".\n", op->o_log_prefix, ent.e_name.bv_val, a.bv_val ); rc = LDAP_OTHER; goto done; } if ( ber_pvt_ber_remaining( &ber ) == 0 ) { break; } attr = op->o_tmpcalloc( 1, sizeof(Attribute), op->o_tmpmemctx ); if ( slap_bv2ad( &a, &attr->a_desc, &text ) != LDAP_SUCCESS) { if ( slap_bv2undef_ad( &a, &attr->a_desc, &text, SLAP_AD_PROXIED ) != LDAP_SUCCESS ) { Debug(LDAP_DEBUG_ANY, "%s meta_send_entry(\"%s\"): " "slap_bv2undef_ad(%s): %s\n", op->o_log_prefix, ent.e_name.bv_val, mapped.bv_val, text ); ( void )ber_scanf( &ber, "x" /* [W] */ ); op->o_tmpfree( attr, op->o_tmpmemctx ); continue; } } if ( attr->a_desc->ad_type->sat_flags & SLAP_AT_SORTED_VAL ) check_sorted_attrs = 1; /* no subschemaSubentry */ if ( attr->a_desc == slap_schema.si_ad_subschemaSubentry || attr->a_desc == slap_schema.si_ad_entryDN ) { /* * We eat target's subschemaSubentry because * a search for this value is likely not * to resolve to the appropriate backend; * later, the local subschemaSubentry is * added. * * We also eat entryDN because the frontend * will reattach it without checking if already * present... */ ( void )ber_scanf( &ber, "x" /* [W] */ ); op->o_tmpfree( attr, op->o_tmpmemctx ); continue; } if ( ber_scanf( &ber, "[W]", &attr->a_vals ) == LBER_ERROR || attr->a_vals == NULL ) { attr->a_vals = (struct berval *)&slap_dummy_bv; } else { for ( last = 0; !BER_BVISNULL( &attr->a_vals[ last ] ); ++last ) ; } attr->a_numvals = last; validate = attr->a_desc->ad_type->sat_syntax->ssyn_validate; pretty = attr->a_desc->ad_type->sat_syntax->ssyn_pretty; if ( !validate && !pretty ) { ber_bvarray_free_x( attr->a_vals, op->o_tmpmemctx ); op->o_tmpfree( attr, op->o_tmpmemctx ); goto next_attr; } /* * It is necessary to try to rewrite attributes with * dn syntax because they might be used in ACLs as * members of groups; since ACLs are applied to the * rewritten stuff, no dn-based subecj clause could * be used at the ldap backend side (see * http://www.OpenLDAP.org/faq/data/cache/452.html) * The problem can be overcome by moving the dn-based * ACLs to the target directory server, and letting * everything pass thru the ldap backend. */ { int i; if ( attr->a_desc->ad_type->sat_syntax == slap_schema.si_syn_distinguishedName ) { asyncmeta_dnattr_result_rewrite( &dc, attr->a_vals ); } else if ( attr->a_desc == slap_schema.si_ad_ref ) { asyncmeta_referral_result_rewrite( &dc, attr->a_vals ); } for ( i = 0; i < last; i++ ) { struct berval pval; int rc; if ( pretty ) { rc = ordered_value_pretty( attr->a_desc, &attr->a_vals[i], &pval, op->o_tmpmemctx ); } else { rc = ordered_value_validate( attr->a_desc, &attr->a_vals[i], 0 ); } if ( rc ) { ber_memfree_x( attr->a_vals[i].bv_val, op->o_tmpmemctx ); if ( --last == i ) { BER_BVZERO( &attr->a_vals[ i ] ); break; } attr->a_vals[i] = attr->a_vals[last]; BER_BVZERO( &attr->a_vals[last] ); i--; continue; } if ( pretty ) { ber_memfree_x( attr->a_vals[i].bv_val, op->o_tmpmemctx ); attr->a_vals[i] = pval; } } if ( last == 0 && attr->a_vals != &slap_dummy_bv ) { ber_bvarray_free_x( attr->a_vals, op->o_tmpmemctx ); op->o_tmpfree( attr, op->o_tmpmemctx ); goto next_attr; } } if ( last && attr->a_desc->ad_type->sat_equality && attr->a_desc->ad_type->sat_equality->smr_normalize ) { int i; attr->a_nvals = op->o_tmpalloc( ( last + 1 ) * sizeof( struct berval ), op->o_tmpmemctx ); for ( i = 0; i<last; i++ ) { /* if normalizer fails, drop this value */ if ( ordered_value_normalize( SLAP_MR_VALUE_OF_ATTRIBUTE_SYNTAX, attr->a_desc, attr->a_desc->ad_type->sat_equality, &attr->a_vals[i], &attr->a_nvals[i], op->o_tmpmemctx )) { ber_memfree_x( attr->a_vals[i].bv_val, op->o_tmpmemctx ); if ( --last == i ) { BER_BVZERO( &attr->a_vals[ i ] ); break; } attr->a_vals[i] = attr->a_vals[last]; BER_BVZERO( &attr->a_vals[last] ); i--; } } BER_BVZERO( &attr->a_nvals[i] ); if ( last == 0 ) { ber_bvarray_free_x( attr->a_vals, op->o_tmpmemctx ); ber_bvarray_free_x( attr->a_nvals, op->o_tmpmemctx ); op->o_tmpfree( attr, op->o_tmpmemctx ); goto next_attr; } } else { attr->a_nvals = attr->a_vals; } attr->a_numvals = last; *attrp = attr; attrp = &attr->a_next; next_attr:; } /* Check for sorted attributes */ if ( check_sorted_attrs ) { for ( attr = ent.e_attrs; attr; attr = attr->a_next ) { if ( attr->a_desc->ad_type->sat_flags & SLAP_AT_SORTED_VAL ) { while ( attr->a_numvals > 1 ) { int i; int rc = slap_sort_vals( (Modifications *)attr, &text, &i, op->o_tmpmemctx ); if ( rc != LDAP_TYPE_OR_VALUE_EXISTS ) break; /* Strip duplicate values */ if ( attr->a_nvals != attr->a_vals ) ber_memfree_x( attr->a_nvals[i].bv_val, op->o_tmpmemctx ); ber_memfree_x( attr->a_vals[i].bv_val, op->o_tmpmemctx ); attr->a_numvals--; if ( (unsigned)i < attr->a_numvals ) { attr->a_vals[i] = attr->a_vals[attr->a_numvals]; if ( attr->a_nvals != attr->a_vals ) attr->a_nvals[i] = attr->a_nvals[attr->a_numvals]; } BER_BVZERO(&attr->a_vals[attr->a_numvals]); if ( attr->a_nvals != attr->a_vals ) BER_BVZERO(&attr->a_nvals[attr->a_numvals]); } attr->a_flags |= SLAP_ATTR_SORTED_VALS; } } } Debug( LDAP_DEBUG_TRACE, "%s asyncmeta_send_entry(\"%s\"): " ".\n", op->o_log_prefix, ent.e_name.bv_val ); ldap_get_entry_controls( mc->mc_conns[target].msc_ldr, e, &rs->sr_ctrls ); rs->sr_entry = &ent; rs->sr_attrs = op->ors_attrs; rs->sr_operational_attrs = NULL; rs->sr_flags = mi->mi_targets[ target ]->mt_rep_flags; rs->sr_err = LDAP_SUCCESS; rc = send_search_entry( op, rs ); switch ( rc ) { case LDAP_UNAVAILABLE: rc = LDAP_OTHER; break; } done:; if ( rs->sr_ctrls != NULL ) { ldap_controls_free( rs->sr_ctrls ); rs->sr_ctrls = NULL; } #if 0 while ( ent.e_attrs ) { attr = ent.e_attrs; ent.e_attrs = attr->a_next; if ( attr->a_nvals != attr->a_vals ) ber_bvarray_free_x( attr->a_nvals, op->o_tmpmemctx ); ber_bvarray_free_x( attr->a_vals, op->o_tmpmemctx ); op->o_tmpfree( attr, op->o_tmpmemctx ); } if (ent.e_name.bv_val != NULL) { op->o_tmpfree( ent.e_name.bv_val, op->o_tmpmemctx ); } if (ent.e_nname.bv_val != NULL) { op->o_tmpfree( ent.e_nname.bv_val, op->o_tmpmemctx ); } if (rs->sr_entry && rs->sr_entry != &ent) { entry_free( rs->sr_entry ); } #endif slap_sl_release( mem_mark, op->o_tmpmemctx ); rs->sr_entry = NULL; rs->sr_attrs = NULL; return rc; }
int ldap_back_referral_result_rewrite( dncookie *dc, BerVarray a_vals, void *memctx ) { int i, last; assert( dc != NULL ); assert( a_vals != NULL ); for ( last = 0; !BER_BVISNULL( &a_vals[ last ] ); last++ ) ; last--; for ( i = 0; !BER_BVISNULL( &a_vals[ i ] ); i++ ) { struct berval dn, olddn = BER_BVNULL; int rc; LDAPURLDesc *ludp; rc = ldap_url_parse( a_vals[ i ].bv_val, &ludp ); if ( rc != LDAP_URL_SUCCESS ) { /* leave attr untouched if massage failed */ continue; } /* FIXME: URLs like "ldap:///dc=suffix" if passed * thru ldap_url_parse() and ldap_url_desc2str() * get rewritten as "ldap:///dc=suffix??base"; * we don't want this to occur... */ if ( ludp->lud_scope == LDAP_SCOPE_BASE ) { ludp->lud_scope = LDAP_SCOPE_DEFAULT; } ber_str2bv( ludp->lud_dn, 0, 0, &olddn ); rc = ldap_back_dn_massage( dc, &olddn, &dn ); switch ( rc ) { case LDAP_UNWILLING_TO_PERFORM: /* * FIXME: need to check if it may be considered * legal to trim values when adding/modifying; * it should be when searching (e.g. ACLs). */ ber_memfree( a_vals[ i ].bv_val ); if ( last > i ) { a_vals[ i ] = a_vals[ last ]; } BER_BVZERO( &a_vals[ last ] ); last--; i--; break; default: /* leave attr untouched if massage failed */ if ( !BER_BVISNULL( &dn ) && olddn.bv_val != dn.bv_val ) { char *newurl; ludp->lud_dn = dn.bv_val; newurl = ldap_url_desc2str( ludp ); free( dn.bv_val ); if ( newurl == NULL ) { /* FIXME: leave attr untouched * even if ldap_url_desc2str failed... */ break; } ber_memfree_x( a_vals[ i ].bv_val, memctx ); ber_str2bv_x( newurl, 0, 1, &a_vals[ i ], memctx ); ber_memfree( newurl ); ludp->lud_dn = olddn.bv_val; } break; } ldap_free_urldesc( ludp ); } return 0; }
/* * Do basic attribute type checking and syntax validation. */ int slap_mods_check( Operation *op, Modifications *ml, const char **text, char *textbuf, size_t textlen, void *ctx ) { int rc; for( ; ml != NULL; ml = ml->sml_next ) { AttributeDescription *ad = NULL; /* convert to attribute description */ if ( ml->sml_desc == NULL ) { rc = slap_bv2ad( &ml->sml_type, &ml->sml_desc, text ); if( rc != LDAP_SUCCESS ) { if ( get_no_schema_check( op )) { rc = slap_bv2undef_ad( &ml->sml_type, &ml->sml_desc, text, 0 ); } } if( rc != LDAP_SUCCESS ) { snprintf( textbuf, textlen, "%s: %s", ml->sml_type.bv_val, *text ); *text = textbuf; return rc; } } ad = ml->sml_desc; if( slap_syntax_is_binary( ad->ad_type->sat_syntax ) && !slap_ad_is_binary( ad )) { /* attribute requires binary transfer */ snprintf( textbuf, textlen, "%s: requires ;binary transfer", ml->sml_type.bv_val ); *text = textbuf; return LDAP_UNDEFINED_TYPE; } if( !slap_syntax_is_binary( ad->ad_type->sat_syntax ) && slap_ad_is_binary( ad )) { /* attribute does not require binary transfer */ snprintf( textbuf, textlen, "%s: disallows ;binary transfer", ml->sml_type.bv_val ); *text = textbuf; return LDAP_UNDEFINED_TYPE; } if( slap_ad_is_tag_range( ad )) { /* attribute requires binary transfer */ snprintf( textbuf, textlen, "%s: inappropriate use of tag range option", ml->sml_type.bv_val ); *text = textbuf; return LDAP_UNDEFINED_TYPE; } #if 0 if ( is_at_obsolete( ad->ad_type ) && (( ml->sml_op != LDAP_MOD_REPLACE && ml->sml_op != LDAP_MOD_DELETE ) || ml->sml_values != NULL )) { /* * attribute is obsolete, * only allow replace/delete with no values */ snprintf( textbuf, textlen, "%s: attribute is obsolete", ml->sml_type.bv_val ); *text = textbuf; return LDAP_CONSTRAINT_VIOLATION; } #endif if ( ml->sml_op == LDAP_MOD_INCREMENT && #ifdef SLAPD_REAL_SYNTAX !is_at_syntax( ad->ad_type, SLAPD_REAL_SYNTAX ) && #endif !is_at_syntax( ad->ad_type, SLAPD_INTEGER_SYNTAX ) ) { /* * attribute values must be INTEGER or REAL */ snprintf( textbuf, textlen, "%s: attribute syntax inappropriate for increment", ml->sml_type.bv_val ); *text = textbuf; return LDAP_CONSTRAINT_VIOLATION; } /* * check values */ if( ml->sml_values != NULL ) { ber_len_t nvals; slap_syntax_validate_func *validate = ad->ad_type->sat_syntax->ssyn_validate; slap_syntax_transform_func *pretty = ad->ad_type->sat_syntax->ssyn_pretty; if( !pretty && !validate ) { *text = "no validator for syntax"; snprintf( textbuf, textlen, "%s: no validator for syntax %s", ml->sml_type.bv_val, ad->ad_type->sat_syntax->ssyn_oid ); *text = textbuf; return LDAP_INVALID_SYNTAX; } /* * check that each value is valid per syntax * and pretty if appropriate */ for ( nvals = 0; !BER_BVISNULL( &ml->sml_values[nvals] ); nvals++ ) { struct berval pval; if ( pretty ) { rc = ordered_value_pretty( ad, &ml->sml_values[nvals], &pval, ctx ); } else { rc = ordered_value_validate( ad, &ml->sml_values[nvals], ml->sml_op ); } if( rc != 0 ) { snprintf( textbuf, textlen, "%s: value #%ld invalid per syntax", ml->sml_type.bv_val, (long) nvals ); *text = textbuf; return LDAP_INVALID_SYNTAX; } if( pretty ) { ber_memfree_x( ml->sml_values[nvals].bv_val, ctx ); ml->sml_values[nvals] = pval; } } ml->sml_values[nvals].bv_len = 0; ml->sml_numvals = nvals; /* * a rough single value check... an additional check is needed * to catch add of single value to existing single valued attribute */ if ((ml->sml_op == LDAP_MOD_ADD || ml->sml_op == LDAP_MOD_REPLACE) && nvals > 1 && is_at_single_value( ad->ad_type )) { snprintf( textbuf, textlen, "%s: multiple values provided", ml->sml_type.bv_val ); *text = textbuf; return LDAP_CONSTRAINT_VIOLATION; } /* if the type has a normalizer, generate the * normalized values. otherwise leave them NULL. * * this is different from the rule for attributes * in an entry - in an attribute list, the normalized * value is set equal to the non-normalized value * when there is no normalizer. */ if( nvals && ad->ad_type->sat_equality && ad->ad_type->sat_equality->smr_normalize ) { ml->sml_nvalues = ber_memalloc_x( (nvals+1)*sizeof(struct berval), ctx ); for ( nvals = 0; !BER_BVISNULL( &ml->sml_values[nvals] ); nvals++ ) { rc = ordered_value_normalize( SLAP_MR_VALUE_OF_ATTRIBUTE_SYNTAX, ad, ad->ad_type->sat_equality, &ml->sml_values[nvals], &ml->sml_nvalues[nvals], ctx ); if ( rc ) { Debug( LDAP_DEBUG_ANY, "<= str2entry NULL (ssyn_normalize %d)\n", rc, 0, 0 ); snprintf( textbuf, textlen, "%s: value #%ld normalization failed", ml->sml_type.bv_val, (long) nvals ); *text = textbuf; BER_BVZERO( &ml->sml_nvalues[nvals] ); return rc; } } BER_BVZERO( &ml->sml_nvalues[nvals] ); } /* check for duplicates, but ignore Deletes. */ if( nvals > 1 && ml->sml_op != LDAP_MOD_DELETE ) { int i; rc = slap_sort_vals( ml, text, &i, ctx ); if ( rc == LDAP_TYPE_OR_VALUE_EXISTS ) { /* value exists already */ snprintf( textbuf, textlen, "%s: value #%d provided more than once", ml->sml_desc->ad_cname.bv_val, i ); *text = textbuf; } if ( rc ) return rc; } } else { ml->sml_numvals = 0; } } return LDAP_SUCCESS; }
RETCODE backsql_BindRowAsStrings_x( SQLHSTMT sth, BACKSQL_ROW_NTS *row, void *ctx ) { RETCODE rc; if ( row == NULL ) { return SQL_ERROR; } #ifdef BACKSQL_TRACE Debug( LDAP_DEBUG_TRACE, "==> backsql_BindRowAsStrings()\n", 0, 0, 0 ); #endif /* BACKSQL_TRACE */ rc = SQLNumResultCols( sth, &row->ncols ); if ( rc != SQL_SUCCESS ) { #ifdef BACKSQL_TRACE Debug( LDAP_DEBUG_TRACE, "backsql_BindRowAsStrings(): " "SQLNumResultCols() failed:\n", 0, 0, 0 ); #endif /* BACKSQL_TRACE */ backsql_PrintErrors( SQL_NULL_HENV, SQL_NULL_HDBC, sth, rc ); } else { SQLCHAR colname[ 64 ]; SQLSMALLINT name_len, col_type, col_scale, col_null; UDWORD col_prec; int i; #ifdef BACKSQL_TRACE Debug( LDAP_DEBUG_TRACE, "backsql_BindRowAsStrings: " "ncols=%d\n", (int)row->ncols, 0, 0 ); #endif /* BACKSQL_TRACE */ row->col_names = (BerVarray)ber_memcalloc_x( row->ncols + 1, sizeof( struct berval ), ctx ); if ( row->col_names == NULL ) { goto nomem; } row->col_prec = (UDWORD *)ber_memcalloc_x( row->ncols, sizeof( UDWORD ), ctx ); if ( row->col_prec == NULL ) { goto nomem; } row->col_type = (SQLSMALLINT *)ber_memcalloc_x( row->ncols, sizeof( SQLSMALLINT ), ctx ); if ( row->col_type == NULL ) { goto nomem; } row->cols = (char **)ber_memcalloc_x( row->ncols + 1, sizeof( char * ), ctx ); if ( row->cols == NULL ) { goto nomem; } row->value_len = (SQLINTEGER *)ber_memcalloc_x( row->ncols, sizeof( SQLINTEGER ), ctx ); if ( row->value_len == NULL ) { goto nomem; } if ( 0 ) { nomem: ber_memfree_x( row->col_names, ctx ); row->col_names = NULL; ber_memfree_x( row->col_prec, ctx ); row->col_prec = NULL; ber_memfree_x( row->col_type, ctx ); row->col_type = NULL; ber_memfree_x( row->cols, ctx ); row->cols = NULL; ber_memfree_x( row->value_len, ctx ); row->value_len = NULL; Debug( LDAP_DEBUG_ANY, "backsql_BindRowAsStrings: " "out of memory\n", 0, 0, 0 ); return LDAP_NO_MEMORY; } for ( i = 0; i < row->ncols; i++ ) { SQLSMALLINT TargetType; rc = SQLDescribeCol( sth, (SQLSMALLINT)(i + 1), &colname[ 0 ], (SQLUINTEGER)( sizeof( colname ) - 1 ), &name_len, &col_type, &col_prec, &col_scale, &col_null ); /* FIXME: test rc? */ ber_str2bv_x( (char *)colname, 0, 1, &row->col_names[ i ], ctx ); #ifdef BACKSQL_TRACE Debug( LDAP_DEBUG_TRACE, "backsql_BindRowAsStrings: " "col_name=%s, col_prec[%d]=%d\n", colname, (int)(i + 1), (int)col_prec ); #endif /* BACKSQL_TRACE */ if ( col_type != SQL_CHAR && col_type != SQL_VARCHAR ) { col_prec = MAX_ATTR_LEN; } row->cols[ i ] = (char *)ber_memcalloc_x( col_prec + 1, sizeof( char ), ctx ); row->col_prec[ i ] = col_prec; row->col_type[ i ] = col_type; /* * ITS#3386, ITS#3113 - 20070308 * Note: there are many differences between various DPMS and ODBC * Systems; some support SQL_C_BLOB, SQL_C_BLOB_LOCATOR. YMMV: * This has only been tested on Linux/MySQL/UnixODBC * For BINARY-type Fields (BLOB, etc), read the data as BINARY */ if ( BACKSQL_IS_BINARY( col_type ) ) { #ifdef BACKSQL_TRACE Debug( LDAP_DEBUG_TRACE, "backsql_BindRowAsStrings: " "col_name=%s, col_type[%d]=%d: reading binary data\n", colname, (int)(i + 1), (int)col_type); #endif /* BACKSQL_TRACE */ TargetType = SQL_C_BINARY; } else { /* Otherwise read it as Character data */ #ifdef BACKSQL_TRACE Debug( LDAP_DEBUG_TRACE, "backsql_BindRowAsStrings: " "col_name=%s, col_type[%d]=%d: reading character data\n", colname, (int)(i + 1), (int)col_type); #endif /* BACKSQL_TRACE */ TargetType = SQL_C_CHAR; } rc = SQLBindCol( sth, (SQLUSMALLINT)(i + 1), TargetType, (SQLPOINTER)row->cols[ i ], col_prec + 1, &row->value_len[ i ] ); /* FIXME: test rc? */ } BER_BVZERO( &row->col_names[ i ] ); row->cols[ i ] = NULL; } #ifdef BACKSQL_TRACE Debug( LDAP_DEBUG_TRACE, "<== backsql_BindRowAsStrings()\n", 0, 0, 0 ); #endif /* BACKSQL_TRACE */ return rc; }
/* * Combination of both dnPretty and dnNormalize */ int dnPrettyNormal( Syntax *syntax, struct berval *val, struct berval *pretty, struct berval *normal, void *ctx) { assert( val != NULL ); assert( pretty != NULL ); assert( normal != NULL ); Debug( LDAP_DEBUG_TRACE, ">>> dnPrettyNormal: <%s>\n", val->bv_val ? val->bv_val : "", 0, 0 ); if ( val->bv_len == 0 ) { ber_dupbv_x( pretty, val, ctx ); ber_dupbv_x( normal, val, ctx ); } else if ( val->bv_len > SLAP_LDAPDN_MAXLEN ) { /* too big */ return LDAP_INVALID_SYNTAX; } else { LDAPDN dn = NULL; int rc; pretty->bv_val = NULL; normal->bv_val = NULL; pretty->bv_len = 0; normal->bv_len = 0; /* FIXME: should be liberal in what we accept */ rc = ldap_bv2dn_x( val, &dn, LDAP_DN_FORMAT_LDAP, ctx ); if ( rc != LDAP_SUCCESS ) { return LDAP_INVALID_SYNTAX; } assert( strlen( val->bv_val ) == val->bv_len ); /* * Schema-aware rewrite */ if ( LDAPDN_rewrite( dn, SLAP_LDAPDN_PRETTY, ctx ) != LDAP_SUCCESS ) { ldap_dnfree_x( dn, ctx ); return LDAP_INVALID_SYNTAX; } rc = ldap_dn2bv_x( dn, pretty, LDAP_DN_FORMAT_LDAPV3 | LDAP_DN_PRETTY, ctx ); if ( rc != LDAP_SUCCESS ) { ldap_dnfree_x( dn, ctx ); return LDAP_INVALID_SYNTAX; } if ( LDAPDN_rewrite( dn, 0, ctx ) != LDAP_SUCCESS ) { ldap_dnfree_x( dn, ctx ); ber_memfree_x( pretty->bv_val, ctx ); pretty->bv_val = NULL; pretty->bv_len = 0; return LDAP_INVALID_SYNTAX; } rc = ldap_dn2bv_x( dn, normal, LDAP_DN_FORMAT_LDAPV3 | LDAP_DN_PRETTY, ctx ); ldap_dnfree_x( dn, ctx ); if ( rc != LDAP_SUCCESS ) { ber_memfree_x( pretty->bv_val, ctx ); pretty->bv_val = NULL; pretty->bv_len = 0; return LDAP_INVALID_SYNTAX; } } Debug( LDAP_DEBUG_TRACE, "<<< dnPrettyNormal: <%s>, <%s>\n", pretty->bv_val ? pretty->bv_val : "", normal->bv_val ? normal->bv_val : "", 0 ); return LDAP_SUCCESS; }
int meta_back_db_destroy( Backend *be, ConfigReply *cr ) { metainfo_t *mi; if ( be->be_private ) { int i; mi = ( metainfo_t * )be->be_private; /* * Destroy the connection tree */ ldap_pvt_thread_mutex_lock( &mi->mi_conninfo.lai_mutex ); if ( mi->mi_conninfo.lai_tree ) { avl_free( mi->mi_conninfo.lai_tree, meta_back_conn_free ); } for ( i = LDAP_BACK_PCONN_FIRST; i < LDAP_BACK_PCONN_LAST; i++ ) { while ( !LDAP_TAILQ_EMPTY( &mi->mi_conn_priv[ i ].mic_priv ) ) { metaconn_t *mc = LDAP_TAILQ_FIRST( &mi->mi_conn_priv[ i ].mic_priv ); LDAP_TAILQ_REMOVE( &mi->mi_conn_priv[ i ].mic_priv, mc, mc_q ); meta_back_conn_free( mc ); } } /* * Destroy the per-target stuff (assuming there's at * least one ...) */ if ( mi->mi_targets != NULL ) { for ( i = 0; i < mi->mi_ntargets; i++ ) { metatarget_t *mt = mi->mi_targets[ i ]; if ( META_BACK_TGT_QUARANTINE( mt ) ) { if ( mt->mt_quarantine.ri_num != mi->mi_quarantine.ri_num ) { mi->mi_ldap_extra->retry_info_destroy( &mt->mt_quarantine ); } ldap_pvt_thread_mutex_destroy( &mt->mt_quarantine_mutex ); } target_free( mt ); } free( mi->mi_targets ); } ldap_pvt_thread_mutex_lock( &mi->mi_cache.mutex ); if ( mi->mi_cache.tree ) { avl_free( mi->mi_cache.tree, meta_dncache_free ); } ldap_pvt_thread_mutex_unlock( &mi->mi_cache.mutex ); ldap_pvt_thread_mutex_destroy( &mi->mi_cache.mutex ); ldap_pvt_thread_mutex_unlock( &mi->mi_conninfo.lai_mutex ); ldap_pvt_thread_mutex_destroy( &mi->mi_conninfo.lai_mutex ); if ( mi->mi_candidates != NULL ) { ber_memfree_x( mi->mi_candidates, NULL ); } if ( META_BACK_QUARANTINE( mi ) ) { mi->mi_ldap_extra->retry_info_destroy( &mi->mi_quarantine ); } } free( be->be_private ); return 0; }
static int map_attr_value( dncookie *dc, AttributeDescription **adp, struct berval *mapped_attr, struct berval *value, struct berval *mapped_value, int remap, void *memctx ) { struct berval vtmp = BER_BVNULL; int freeval = 0; AttributeDescription *ad = *adp; struct ldapmapping *mapping = NULL; rwm_mapping( &dc->rwmap->rwm_at, &ad->ad_cname, &mapping, remap ); if ( mapping == NULL ) { if ( dc->rwmap->rwm_at.drop_missing ) { return -1; } *mapped_attr = ad->ad_cname; } else { *mapped_attr = mapping->m_dst; } if ( value != NULL ) { assert( mapped_value != NULL ); if ( ad->ad_type->sat_syntax == slap_schema.si_syn_distinguishedName || ( mapping != NULL && mapping->m_dst_ad->ad_type->sat_syntax == slap_schema.si_syn_distinguishedName ) ) { dncookie fdc = *dc; int rc; fdc.ctx = "searchFilterAttrDN"; vtmp = *value; rc = rwm_dn_massage_normalize( &fdc, value, &vtmp ); switch ( rc ) { case LDAP_SUCCESS: if ( vtmp.bv_val != value->bv_val ) { freeval = 1; } break; case LDAP_UNWILLING_TO_PERFORM: case LDAP_OTHER: default: return -1; } } else if ( ad->ad_type->sat_equality && ( ad->ad_type->sat_equality->smr_usage & SLAP_MR_MUTATION_NORMALIZER ) ) { if ( ad->ad_type->sat_equality->smr_normalize( (SLAP_MR_DENORMALIZE|SLAP_MR_VALUE_OF_ASSERTION_SYNTAX), NULL, NULL, value, &vtmp, memctx ) ) { return -1; } freeval = 2; } else if ( ad == slap_schema.si_ad_objectClass || ad == slap_schema.si_ad_structuralObjectClass ) { rwm_map( &dc->rwmap->rwm_oc, value, &vtmp, remap ); if ( BER_BVISNULL( &vtmp ) || BER_BVISEMPTY( &vtmp ) ) { vtmp = *value; } } else { vtmp = *value; } filter_escape_value_x( &vtmp, mapped_value, memctx ); switch ( freeval ) { case 1: ch_free( vtmp.bv_val ); break; case 2: ber_memfree_x( vtmp.bv_val, memctx ); break; } } if ( mapping != NULL ) { assert( mapping->m_dst_ad != NULL ); *adp = mapping->m_dst_ad; } return 0; }
static int dupent_parseCtrl ( Operation *op, SlapReply *rs, LDAPControl *ctrl ) { ber_tag_t tag; BerElementBuffer berbuf; BerElement *ber = (BerElement *)&berbuf; ber_len_t len; BerVarray AttributeDescriptionList = NULL; ber_len_t cnt = sizeof(struct berval); ber_len_t off = 0; ber_int_t PartialApplicationAllowed = 1; dupent_t *ds = NULL; int i; if ( op->o_dupent != SLAP_CONTROL_NONE ) { rs->sr_text = "Dupent control specified multiple times"; return LDAP_PROTOCOL_ERROR; } if ( BER_BVISNULL( &ctrl->ldctl_value ) ) { rs->sr_text = "Dupent control value is absent"; return LDAP_PROTOCOL_ERROR; } if ( BER_BVISEMPTY( &ctrl->ldctl_value ) ) { rs->sr_text = "Dupent control value is empty"; return LDAP_PROTOCOL_ERROR; } ber_init2( ber, &ctrl->ldctl_value, 0 ); /* DuplicateEntryRequest ::= SEQUENCE { AttributeDescriptionList, -- from [RFC2251] PartialApplicationAllowed BOOLEAN DEFAULT TRUE } AttributeDescriptionList ::= SEQUENCE OF AttributeDescription AttributeDescription ::= LDAPString attributeDescription = AttributeType [ ";" <options> ] */ tag = ber_skip_tag( ber, &len ); if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX; if ( ber_scanf( ber, "{M}", &AttributeDescriptionList, &cnt, off ) == LBER_ERROR ) { rs->sr_text = "Dupent control: dupentSpec decoding error"; rs->sr_err = LDAP_PROTOCOL_ERROR; goto done; } tag = ber_skip_tag( ber, &len ); if ( tag == LBER_BOOLEAN ) { /* NOTE: PartialApplicationAllowed is ignored, since the control * can always be honored */ if ( ber_scanf( ber, "b", &PartialApplicationAllowed ) == LBER_ERROR ) { rs->sr_text = "Dupent control: dupentSpec decoding error"; rs->sr_err = LDAP_PROTOCOL_ERROR; goto done; } tag = ber_skip_tag( ber, &len ); } if ( len || tag != LBER_DEFAULT ) { rs->sr_text = "Dupent control: dupentSpec decoding error"; rs->sr_err = LDAP_PROTOCOL_ERROR; goto done; } ds = (dupent_t *)op->o_tmpcalloc( 1, sizeof(dupent_t) + sizeof(AttributeName)*cnt, op->o_tmpmemctx ); ds->ds_paa = PartialApplicationAllowed; if ( cnt == 0 ) { ds->ds_flags |= SLAP_USERATTRS_YES; } else { int c; ds->ds_an = (AttributeName *)&ds[ 1 ]; for ( i = 0, c = 0; i < cnt; i++ ) { const char *text; int j; int rc; AttributeDescription *ad = NULL; if ( bvmatch( &AttributeDescriptionList[i], slap_bv_all_user_attrs ) ) { if ( ds->ds_flags & SLAP_USERATTRS_YES ) { rs->sr_text = "Dupent control: AttributeDescription decoding error"; rs->sr_err = LDAP_PROTOCOL_ERROR; goto done; } ds->ds_flags |= SLAP_USERATTRS_YES; continue; } rc = slap_bv2ad( &AttributeDescriptionList[i], &ad, &text ); if ( rc != LDAP_SUCCESS ) { continue; } ds->ds_an[c].an_desc = ad; ds->ds_an[c].an_name = ad->ad_cname; /* FIXME: not specified; consider this an error, just in case */ for ( j = 0; j < c; j++ ) { if ( ds->ds_an[c].an_desc == ds->ds_an[j].an_desc ) { rs->sr_text = "Dupent control: AttributeDescription must be unique within AttributeDescriptionList"; rs->sr_err = LDAP_PROTOCOL_ERROR; goto done; } } c++; } ds->ds_nattrs = c; if ( ds->ds_flags & SLAP_USERATTRS_YES ) { /* purge user attrs */ for ( i = 0; i < ds->ds_nattrs; ) { if ( is_at_operational( ds->ds_an[i].an_desc->ad_type ) ) { i++; continue; } ds->ds_nattrs--; if ( i < ds->ds_nattrs ) { ds->ds_an[i] = ds->ds_an[ds->ds_nattrs]; } } } } op->o_ctrldupent = (void *)ds; op->o_dupent = ctrl->ldctl_iscritical ? SLAP_CONTROL_CRITICAL : SLAP_CONTROL_NONCRITICAL; rs->sr_err = LDAP_SUCCESS; done:; if ( rs->sr_err != LDAP_SUCCESS ) { op->o_tmpfree( ds, op->o_tmpmemctx ); } if ( AttributeDescriptionList != NULL ) { ber_memfree_x( AttributeDescriptionList, op->o_tmpmemctx ); } return rs->sr_err; }
static int OpenLDAPaciPrettyNormal( struct berval *val, struct berval *out, void *ctx, int normalize ) { struct berval oid = BER_BVNULL, scope = BER_BVNULL, rights = BER_BVNULL, nrights = BER_BVNULL, type = BER_BVNULL, ntype = BER_BVNULL, subject = BER_BVNULL, nsubject = BER_BVNULL; int idx, rc = LDAP_SUCCESS, freesubject = 0, freetype = 0; char *ptr; BER_BVZERO( out ); if ( BER_BVISEMPTY( val ) ) { Debug( LDAP_DEBUG_ACL, "aciPrettyNormal: value is empty\n" ); return LDAP_INVALID_SYNTAX; } /* oid: if valid, it's already normalized */ if ( acl_get_part( val, 0, '#', &oid ) < 0 || numericoidValidate( NULL, &oid ) != LDAP_SUCCESS ) { Debug( LDAP_DEBUG_ACL, "aciPrettyNormal: invalid oid '%s'\n", oid.bv_val ); return LDAP_INVALID_SYNTAX; } /* scope: normalize by replacing with OpenLDAPaciscopes */ if ( acl_get_part( val, 1, '#', &scope ) < 0 ) { Debug( LDAP_DEBUG_ACL, "aciPrettyNormal: missing scope in '%s'\n", val->bv_val ); return LDAP_INVALID_SYNTAX; } idx = bv_getcaseidx( &scope, OpenLDAPaciscopes ); if ( idx == -1 ) { Debug( LDAP_DEBUG_ACL, "aciPrettyNormal: invalid scope '%s'\n", scope.bv_val ); return LDAP_INVALID_SYNTAX; } scope = *OpenLDAPaciscopes[ idx ]; /* rights */ if ( acl_get_part( val, 2, '#', &rights ) < 0 ) { Debug( LDAP_DEBUG_ACL, "aciPrettyNormal: missing rights in '%s'\n", val->bv_val ); return LDAP_INVALID_SYNTAX; } if ( OpenLDAPaciNormalizeRights( &rights, &nrights, ctx ) != LDAP_SUCCESS ) { return LDAP_INVALID_SYNTAX; } /* type */ if ( acl_get_part( val, 3, '#', &type ) < 0 ) { Debug( LDAP_DEBUG_ACL, "aciPrettyNormal: missing type in '%s'\n", val->bv_val ); rc = LDAP_INVALID_SYNTAX; goto cleanup; } idx = bv_getcaseidx( &type, OpenLDAPacitypes ); if ( idx == -1 ) { struct berval isgr; if ( acl_get_part( &type, 0, '/', &isgr ) < 0 ) { Debug( LDAP_DEBUG_ACL, "aciPrettyNormal: invalid type '%s'\n", type.bv_val ); rc = LDAP_INVALID_SYNTAX; goto cleanup; } idx = bv_getcaseidx( &isgr, OpenLDAPacitypes ); if ( idx == -1 || idx >= LAST_OPTIONAL ) { Debug( LDAP_DEBUG_ACL, "aciPrettyNormal: invalid type '%s'\n", isgr.bv_val ); rc = LDAP_INVALID_SYNTAX; goto cleanup; } } ntype = *OpenLDAPacitypes[ idx ]; /* subject */ bv_get_tail( val, &type, &subject ); if ( BER_BVISEMPTY( &subject ) || subject.bv_val[ 0 ] != '#' ) { Debug( LDAP_DEBUG_ACL, "aciPrettyNormal: missing subject in '%s'\n", val->bv_val ); rc = LDAP_INVALID_SYNTAX; goto cleanup; } subject.bv_val++; subject.bv_len--; if ( idx < LAST_DNVALUED ) { /* FIXME: pass DN syntax? */ if ( normalize ) { rc = dnNormalize( 0, NULL, NULL, &subject, &nsubject, ctx ); } else { rc = dnPretty( NULL, &subject, &nsubject, ctx ); } if ( rc == LDAP_SUCCESS ) { freesubject = 1; } else { Debug( LDAP_DEBUG_ACL, "aciPrettyNormal: invalid subject dn '%s'\n", subject.bv_val ); goto cleanup; } if ( OpenLDAPacitypes[ idx ] == &aci_bv[ ACI_BV_GROUP ] || OpenLDAPacitypes[ idx ] == &aci_bv[ ACI_BV_ROLE ] ) { /* do {group|role}/oc/at check */ struct berval ocbv = BER_BVNULL, atbv = BER_BVNULL; ocbv.bv_val = ber_bvchr( &type, '/' ); if ( ocbv.bv_val != NULL ) { ObjectClass *oc = NULL; AttributeDescription *ad = NULL; const char *text = NULL; int rc; struct berval bv; bv.bv_len = ntype.bv_len; ocbv.bv_val++; ocbv.bv_len = type.bv_len - ( ocbv.bv_val - type.bv_val ); atbv.bv_val = ber_bvchr( &ocbv, '/' ); if ( atbv.bv_val != NULL ) { atbv.bv_val++; atbv.bv_len = type.bv_len - ( atbv.bv_val - type.bv_val ); ocbv.bv_len = atbv.bv_val - ocbv.bv_val - 1; rc = slap_bv2ad( &atbv, &ad, &text ); if ( rc != LDAP_SUCCESS ) { Debug( LDAP_DEBUG_ACL, "aciPrettyNormal: unknown group attribute '%s'\n", atbv.bv_val ); rc = LDAP_INVALID_SYNTAX; goto cleanup; } bv.bv_len += STRLENOF( "/" ) + ad->ad_cname.bv_len; } oc = oc_bvfind( &ocbv ); if ( oc == NULL ) { Debug( LDAP_DEBUG_ACL, "aciPrettyNormal: invalid group '%s'\n", ocbv.bv_val ); rc = LDAP_INVALID_SYNTAX; goto cleanup; } bv.bv_len += STRLENOF( "/" ) + oc->soc_cname.bv_len; bv.bv_val = ber_memalloc_x( bv.bv_len + 1, ctx ); ptr = bv.bv_val; ptr = lutil_strncopy( ptr, ntype.bv_val, ntype.bv_len ); ptr[ 0 ] = '/'; ptr++; ptr = lutil_strncopy( ptr, oc->soc_cname.bv_val, oc->soc_cname.bv_len ); if ( ad != NULL ) { ptr[ 0 ] = '/'; ptr++; ptr = lutil_strncopy( ptr, ad->ad_cname.bv_val, ad->ad_cname.bv_len ); } ptr[ 0 ] = '\0'; ntype = bv; freetype = 1; } } } else if ( OpenLDAPacitypes[ idx ] == &aci_bv[ ACI_BV_DNATTR ] ) { AttributeDescription *ad = NULL; const char *text = NULL; int rc; rc = slap_bv2ad( &subject, &ad, &text ); if ( rc != LDAP_SUCCESS ) { Debug( LDAP_DEBUG_ACL, "aciPrettyNormal: unknown dn attribute '%s'\n", subject.bv_val ); rc = LDAP_INVALID_SYNTAX; goto cleanup; } if ( ad->ad_type->sat_syntax != slap_schema.si_syn_distinguishedName ) { /* FIXME: allow nameAndOptionalUID? */ Debug( LDAP_DEBUG_ACL, "aciPrettyNormal: wrong syntax for dn attribute '%s'\n", subject.bv_val ); rc = LDAP_INVALID_SYNTAX; goto cleanup; } nsubject = ad->ad_cname; } else if ( OpenLDAPacitypes[ idx ] == &aci_bv[ ACI_BV_SET ] || OpenLDAPacitypes[ idx ] == &aci_bv[ ACI_BV_SET_REF ] ) { /* NOTE: dunno how to normalize it... */ nsubject = subject; } out->bv_len = oid.bv_len + STRLENOF( "#" ) + scope.bv_len + STRLENOF( "#" ) + nrights.bv_len + STRLENOF( "#" ) + ntype.bv_len + STRLENOF( "#" ) + nsubject.bv_len; out->bv_val = ber_memalloc_x( out->bv_len + 1, ctx ); ptr = lutil_strncopy( out->bv_val, oid.bv_val, oid.bv_len ); ptr[ 0 ] = '#'; ptr++; ptr = lutil_strncopy( ptr, scope.bv_val, scope.bv_len ); ptr[ 0 ] = '#'; ptr++; ptr = lutil_strncopy( ptr, nrights.bv_val, nrights.bv_len ); ptr[ 0 ] = '#'; ptr++; ptr = lutil_strncopy( ptr, ntype.bv_val, ntype.bv_len ); ptr[ 0 ] = '#'; ptr++; if ( !BER_BVISNULL( &nsubject ) ) { ptr = lutil_strncopy( ptr, nsubject.bv_val, nsubject.bv_len ); } ptr[ 0 ] = '\0'; cleanup:; if ( freesubject ) { ber_memfree_x( nsubject.bv_val, ctx ); } if ( freetype ) { ber_memfree_x( ntype.bv_val, ctx ); } if ( !BER_BVISNULL( &nrights ) ) { ber_memfree_x( nrights.bv_val, ctx ); } return rc; }
static int LDAPRDN_rewrite( LDAPRDN rdn, unsigned flags, void *ctx ) { int rc, iAVA, do_sort = 0; for ( iAVA = 0; rdn[ iAVA ]; iAVA++ ) { LDAPAVA *ava = rdn[ iAVA ]; AttributeDescription *ad; slap_syntax_validate_func *validf = NULL; slap_mr_normalize_func *normf = NULL; slap_syntax_transform_func *transf = NULL; MatchingRule *mr = NULL; struct berval bv = BER_BVNULL; assert( ava != NULL ); if ( ( ad = AVA_PRIVATE( ava ) ) == NULL ) { const char *text = NULL; rc = slap_bv2ad( &ava->la_attr, &ad, &text ); if ( rc != LDAP_SUCCESS ) { rc = slap_bv2undef_ad( &ava->la_attr, &ad, &text, SLAP_AD_PROXIED|slap_DN_strict ); if ( rc != LDAP_SUCCESS ) { return LDAP_INVALID_SYNTAX; } } ava->la_private = ( void * )ad; do_sort = 1; } /* * Replace attr oid/name with the canonical name */ ava->la_attr = ad->ad_cname; if( ava->la_flags & LDAP_AVA_BINARY ) { /* AVA is binary encoded, not supported */ return LDAP_INVALID_SYNTAX; /* Do not allow X-ORDERED 'VALUES' naming attributes */ } else if( ad->ad_type->sat_flags & SLAP_AT_ORDERED_VAL ) { return LDAP_INVALID_SYNTAX; } else if( flags & SLAP_LDAPDN_PRETTY ) { transf = ad->ad_type->sat_syntax->ssyn_pretty; if( !transf ) { validf = ad->ad_type->sat_syntax->ssyn_validate; } } else { /* normalization */ validf = ad->ad_type->sat_syntax->ssyn_validate; mr = ad->ad_type->sat_equality; if( mr && (!( mr->smr_usage & SLAP_MR_MUTATION_NORMALIZER ))) { normf = mr->smr_normalize; } } if ( validf ) { /* validate value before normalization */ rc = ( *validf )( ad->ad_type->sat_syntax, ava->la_value.bv_len ? &ava->la_value : (struct berval *) &slap_empty_bv ); if ( rc != LDAP_SUCCESS ) { return LDAP_INVALID_SYNTAX; } } if ( transf ) { /* * transform value by pretty function * if value is empty, use empty_bv */ rc = ( *transf )( ad->ad_type->sat_syntax, ava->la_value.bv_len ? &ava->la_value : (struct berval *) &slap_empty_bv, &bv, ctx ); if ( rc != LDAP_SUCCESS ) { return LDAP_INVALID_SYNTAX; } } if ( normf ) { /* * normalize value * if value is empty, use empty_bv */ rc = ( *normf )( SLAP_MR_VALUE_OF_ASSERTION_SYNTAX, ad->ad_type->sat_syntax, mr, ava->la_value.bv_len ? &ava->la_value : (struct berval *) &slap_empty_bv, &bv, ctx ); if ( rc != LDAP_SUCCESS ) { return LDAP_INVALID_SYNTAX; } } if( bv.bv_val ) { if ( ava->la_flags & LDAP_AVA_FREE_VALUE ) ber_memfree_x( ava->la_value.bv_val, ctx ); ava->la_value = bv; ava->la_flags |= LDAP_AVA_FREE_VALUE; } /* reject empty values */ if (!ava->la_value.bv_len) { return LDAP_INVALID_SYNTAX; } } rc = LDAP_SUCCESS; if ( do_sort ) { rc = AVA_Sort( rdn, iAVA ); } return rc; }