/* * massages "in" and prettifies and normalizes it into "pdn" and "ndn" * * "pdn" may be untouched if no massaging occurred and its value was not null; * "ndn" may be untouched if no massaging occurred and its value was not null; * if no massage occurred and "ndn" value was not null, it is filled * with the normaized value of "pdn", much like ndn = dnNormalize( pdn ) */ int rwm_dn_massage_pretty_normalize( dncookie *dc, struct berval *in, struct berval *pdn, struct berval *ndn ) { int rc; struct berval mdn = BER_BVNULL; /* massage, pretty and normalize a DN */ rc = rwm_dn_massage( dc, in, &mdn ); if ( rc != LDAP_SUCCESS ) { return rc; } if ( mdn.bv_val == in->bv_val && !BER_BVISNULL( pdn ) ) { if ( BER_BVISNULL( ndn ) ) { rc = dnNormalize( 0, NULL, NULL, &mdn, ndn, NULL ); } return rc; } rc = dnPrettyNormal( NULL, &mdn, pdn, ndn, NULL ); if ( mdn.bv_val != in->bv_val ) { ch_free( mdn.bv_val ); } return rc; }
static int pblock_set_dn( void *value, struct berval *dn, struct berval *ndn, void *memctx ) { struct berval bv; if ( !BER_BVISNULL( dn )) { slap_sl_free( dn->bv_val, memctx ); BER_BVZERO( dn ); } if ( !BER_BVISNULL( ndn )) { slap_sl_free( ndn->bv_val, memctx ); BER_BVZERO( ndn ); } bv.bv_val = (char *)value; bv.bv_len = ( value != NULL ) ? strlen( bv.bv_val ) : 0; return dnPrettyNormal( NULL, &bv, dn, ndn, memctx ); }
int passwd_extop( Operation *op, SlapReply *rs ) { struct berval id = {0, NULL}, hash, *rsp = NULL; req_pwdexop_s *qpw = &op->oq_pwdexop; req_extended_s qext = op->oq_extended; Modifications *ml; slap_callback cb = { NULL, slap_null_cb, NULL, NULL }; int i, nhash; char **hashes, idNul; int rc; BackendDB *op_be; int freenewpw = 0; struct berval dn = BER_BVNULL, ndn = BER_BVNULL; assert( ber_bvcmp( &slap_EXOP_MODIFY_PASSWD, &op->ore_reqoid ) == 0 ); if( op->o_dn.bv_len == 0 ) { Statslog( LDAP_DEBUG_STATS, "%s PASSMOD\n", op->o_log_prefix, 0, 0, 0, 0 ); rs->sr_text = "only authenticated users may change passwords"; return LDAP_STRONG_AUTH_REQUIRED; } qpw->rs_old.bv_len = 0; qpw->rs_old.bv_val = NULL; qpw->rs_new.bv_len = 0; qpw->rs_new.bv_val = NULL; qpw->rs_mods = NULL; qpw->rs_modtail = NULL; rs->sr_err = slap_passwd_parse( op->ore_reqdata, &id, &qpw->rs_old, &qpw->rs_new, &rs->sr_text ); if ( !BER_BVISNULL( &id )) { idNul = id.bv_val[id.bv_len]; id.bv_val[id.bv_len] = '\0'; } if ( rs->sr_err == LDAP_SUCCESS && !BER_BVISEMPTY( &id ) ) { Statslog( LDAP_DEBUG_STATS, "%s PASSMOD id=\"%s\"%s%s\n", op->o_log_prefix, id.bv_val, qpw->rs_old.bv_val ? " old" : "", qpw->rs_new.bv_val ? " new" : "", 0 ); } else { Statslog( LDAP_DEBUG_STATS, "%s PASSMOD%s%s\n", op->o_log_prefix, qpw->rs_old.bv_val ? " old" : "", qpw->rs_new.bv_val ? " new" : "", 0, 0 ); } if ( rs->sr_err != LDAP_SUCCESS ) { if ( !BER_BVISNULL( &id )) id.bv_val[id.bv_len] = idNul; return rs->sr_err; } if ( !BER_BVISEMPTY( &id ) ) { rs->sr_err = dnPrettyNormal( NULL, &id, &dn, &ndn, op->o_tmpmemctx ); id.bv_val[id.bv_len] = idNul; if ( rs->sr_err != LDAP_SUCCESS ) { rs->sr_text = "Invalid DN"; rc = rs->sr_err; goto error_return; } op->o_req_dn = dn; op->o_req_ndn = ndn; op->o_bd = select_backend( &op->o_req_ndn, 1 ); } else { ber_dupbv_x( &dn, &op->o_dn, op->o_tmpmemctx ); ber_dupbv_x( &ndn, &op->o_ndn, op->o_tmpmemctx ); op->o_req_dn = dn; op->o_req_ndn = ndn; ldap_pvt_thread_mutex_lock( &op->o_conn->c_mutex ); op->o_bd = op->o_conn->c_authz_backend; ldap_pvt_thread_mutex_unlock( &op->o_conn->c_mutex ); } if( op->o_bd == NULL ) { if ( qpw->rs_old.bv_val != NULL ) { rs->sr_text = "unwilling to verify old password"; rc = LDAP_UNWILLING_TO_PERFORM; goto error_return; } #ifdef HAVE_CYRUS_SASL rc = slap_sasl_setpass( op, rs ); #else rs->sr_text = "no authz backend"; rc = LDAP_OTHER; #endif goto error_return; } if ( op->o_req_ndn.bv_len == 0 ) { rs->sr_text = "no password is associated with the Root DSE"; rc = LDAP_UNWILLING_TO_PERFORM; goto error_return; } /* 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 ); } if (backend_check_restrictions( op, rs, (struct berval *)&slap_EXOP_MODIFY_PASSWD ) != LDAP_SUCCESS) { rc = rs->sr_err; goto error_return; } /* check for referrals */ if ( backend_check_referrals( op, rs ) != LDAP_SUCCESS ) { rc = rs->sr_err; goto error_return; } /* This does not apply to multi-master case */ if(!( !SLAP_SINGLE_SHADOW( op->o_bd ) || be_isupdate( op ))) { /* we SHOULD return a referral in this case */ BerVarray defref = op->o_bd->be_update_refs ? op->o_bd->be_update_refs : default_referral; if( defref != NULL ) { rs->sr_ref = referral_rewrite( op->o_bd->be_update_refs, NULL, NULL, LDAP_SCOPE_DEFAULT ); if(rs->sr_ref) { rs->sr_flags |= REP_REF_MUSTBEFREED; } else { rs->sr_ref = defref; } rc = LDAP_REFERRAL; goto error_return; } rs->sr_text = "shadow context; no update referral"; rc = LDAP_UNWILLING_TO_PERFORM; goto error_return; } /* generate a new password if none was provided */ if ( qpw->rs_new.bv_len == 0 ) { slap_passwd_generate( &qpw->rs_new ); if ( qpw->rs_new.bv_len ) { rsp = slap_passwd_return( &qpw->rs_new ); freenewpw = 1; } } if ( qpw->rs_new.bv_len == 0 ) { rs->sr_text = "password generation failed"; rc = LDAP_OTHER; goto error_return; } op->o_bd = op_be; /* Give the backend a chance to handle this itself */ if ( op->o_bd->be_extended ) { rs->sr_err = op->o_bd->be_extended( op, rs ); if ( rs->sr_err != LDAP_UNWILLING_TO_PERFORM && rs->sr_err != SLAP_CB_CONTINUE ) { rc = rs->sr_err; if ( rsp ) { rs->sr_rspdata = rsp; rsp = NULL; } goto error_return; } } /* The backend didn't handle it, so try it here */ if( op->o_bd && !op->o_bd->be_modify ) { rs->sr_text = "operation not supported for current user"; rc = LDAP_UNWILLING_TO_PERFORM; goto error_return; } if ( qpw->rs_old.bv_val != NULL ) { Entry *e = NULL; rc = be_entry_get_rw( op, &op->o_req_ndn, NULL, slap_schema.si_ad_userPassword, 0, &e ); if ( rc == LDAP_SUCCESS && e ) { Attribute *a = attr_find( e->e_attrs, slap_schema.si_ad_userPassword ); if ( a ) rc = slap_passwd_check( op, e, a, &qpw->rs_old, &rs->sr_text ); else rc = 1; be_entry_release_r( op, e ); if ( rc == LDAP_SUCCESS ) goto old_good; } rs->sr_text = "unwilling to verify old password"; rc = LDAP_UNWILLING_TO_PERFORM; goto error_return; } old_good: ml = ch_malloc( sizeof(Modifications) ); if ( !qpw->rs_modtail ) qpw->rs_modtail = &ml->sml_next; if ( default_passwd_hash ) { for ( nhash = 0; default_passwd_hash[nhash]; nhash++ ); hashes = default_passwd_hash; } else { nhash = 1; hashes = (char **)defhash; } ml->sml_numvals = nhash; ml->sml_values = ch_malloc( (nhash+1)*sizeof(struct berval) ); for ( i=0; hashes[i]; i++ ) { slap_passwd_hash_type( &qpw->rs_new, &hash, hashes[i], &rs->sr_text ); if ( hash.bv_len == 0 ) { if ( !rs->sr_text ) { rs->sr_text = "password hash failed"; } break; } ml->sml_values[i] = hash; } ml->sml_values[i].bv_val = NULL; ml->sml_nvalues = NULL; ml->sml_desc = slap_schema.si_ad_userPassword; ml->sml_type = ml->sml_desc->ad_cname; ml->sml_op = LDAP_MOD_REPLACE; ml->sml_flags = 0; ml->sml_next = qpw->rs_mods; qpw->rs_mods = ml; if ( hashes[i] ) { rs->sr_err = LDAP_OTHER; } else { slap_callback *sc = op->o_callback; op->o_tag = LDAP_REQ_MODIFY; op->o_callback = &cb; op->orm_modlist = qpw->rs_mods; op->orm_no_opattrs = 0; cb.sc_private = qpw; /* let Modify know this was pwdMod, * if it cares... */ rs->sr_err = op->o_bd->be_modify( op, rs ); /* be_modify() might have shuffled modifications */ qpw->rs_mods = op->orm_modlist; if ( rs->sr_err == LDAP_SUCCESS ) { rs->sr_rspdata = rsp; } else if ( rsp ) { ber_bvfree( rsp ); rsp = NULL; } op->o_tag = LDAP_REQ_EXTENDED; op->o_callback = sc; } rc = rs->sr_err; op->oq_extended = qext; error_return:; if ( qpw->rs_mods ) { slap_mods_free( qpw->rs_mods, 1 ); } if ( freenewpw ) { free( qpw->rs_new.bv_val ); } if ( !BER_BVISNULL( &dn ) ) { op->o_tmpfree( dn.bv_val, op->o_tmpmemctx ); BER_BVZERO( &op->o_req_dn ); } if ( !BER_BVISNULL( &ndn ) ) { op->o_tmpfree( ndn.bv_val, op->o_tmpmemctx ); BER_BVZERO( &op->o_req_ndn ); } return rc; }
static int ldap_back_exop_passwd( Operation *op, SlapReply *rs, ldapconn_t **lcp ) { ldapinfo_t *li = (ldapinfo_t *) op->o_bd->be_private; ldapconn_t *lc = *lcp; req_pwdexop_s *qpw = &op->oq_pwdexop; LDAPMessage *res; ber_int_t msgid; int rc, isproxy, freedn = 0; int do_retry = 1; char *text = NULL; struct berval dn = op->o_req_dn, ndn = op->o_req_ndn; assert( lc != NULL ); assert( rs->sr_ctrls == NULL ); if ( BER_BVISNULL( &ndn ) && op->ore_reqdata != NULL ) { /* NOTE: most of this code is mutated * from slap_passwd_parse(); * But here we only need * the first berval... */ ber_tag_t tag; ber_len_t len = -1; BerElementBuffer berbuf; BerElement *ber = (BerElement *)&berbuf; struct berval tmpid = BER_BVNULL; if ( op->ore_reqdata->bv_len == 0 ) { return LDAP_PROTOCOL_ERROR; } /* ber_init2 uses reqdata directly, doesn't allocate new buffers */ ber_init2( ber, op->ore_reqdata, 0 ); tag = ber_scanf( ber, "{" /*}*/ ); if ( tag == LBER_ERROR ) { return LDAP_PROTOCOL_ERROR; } tag = ber_peek_tag( ber, &len ); if ( tag == LDAP_TAG_EXOP_MODIFY_PASSWD_ID ) { tag = ber_get_stringbv( ber, &tmpid, LBER_BV_NOTERM ); if ( tag == LBER_ERROR ) { return LDAP_PROTOCOL_ERROR; } } if ( !BER_BVISEMPTY( &tmpid ) ) { char idNull = tmpid.bv_val[tmpid.bv_len]; tmpid.bv_val[tmpid.bv_len] = '\0'; rs->sr_err = dnPrettyNormal( NULL, &tmpid, &dn, &ndn, op->o_tmpmemctx ); tmpid.bv_val[tmpid.bv_len] = idNull; if ( rs->sr_err != LDAP_SUCCESS ) { /* should have been successfully parsed earlier! */ return rs->sr_err; } freedn = 1; } else { dn = op->o_dn; ndn = op->o_ndn; } } isproxy = ber_bvcmp( &ndn, &op->o_ndn ); Debug( LDAP_DEBUG_ARGS, "==> ldap_back_exop_passwd(\"%s\")%s\n", dn.bv_val, isproxy ? " (proxy)" : "", 0 ); retry: rc = ldap_passwd( lc->lc_ld, &dn, qpw->rs_old.bv_val ? &qpw->rs_old : NULL, qpw->rs_new.bv_val ? &qpw->rs_new : NULL, op->o_ctrls, NULL, &msgid ); if ( rc == LDAP_SUCCESS ) { /* TODO: set timeout? */ /* by now, make sure no timeout is used (ITS#6282) */ struct timeval tv = { -1, 0 }; if ( ldap_result( lc->lc_ld, msgid, LDAP_MSG_ALL, &tv, &res ) == -1 ) { ldap_get_option( lc->lc_ld, LDAP_OPT_ERROR_NUMBER, &rc ); rs->sr_err = rc; } else { /* only touch when activity actually took place... */ if ( li->li_idle_timeout ) { lc->lc_time = op->o_time; } /* sigh. parse twice, because parse_passwd * doesn't give us the err / match / msg info. */ rc = ldap_parse_result( lc->lc_ld, res, &rs->sr_err, (char **)&rs->sr_matched, &text, NULL, &rs->sr_ctrls, 0 ); if ( rc == LDAP_SUCCESS ) { if ( rs->sr_err == LDAP_SUCCESS ) { struct berval newpw; /* this never happens because * the frontend is generating * the new password, so when * the passwd exop is proxied, * it never delegates password * generation to the remote server */ rc = ldap_parse_passwd( lc->lc_ld, res, &newpw ); if ( rc == LDAP_SUCCESS && !BER_BVISNULL( &newpw ) ) { rs->sr_type = REP_EXTENDED; rs->sr_rspdata = slap_passwd_return( &newpw ); free( newpw.bv_val ); } } else { rc = rs->sr_err; } } ldap_msgfree( res ); } } if ( rc != LDAP_SUCCESS ) { rs->sr_err = slap_map_api2result( rs ); if ( rs->sr_err == LDAP_UNAVAILABLE && do_retry ) { do_retry = 0; if ( ldap_back_retry( &lc, op, rs, LDAP_BACK_SENDERR ) ) { goto retry; } } if ( LDAP_BACK_QUARANTINE( li ) ) { ldap_back_quarantine( op, rs ); } if ( text ) rs->sr_text = text; send_ldap_extended( op, rs ); /* otherwise frontend resends result */ rc = rs->sr_err = SLAPD_ABANDON; } else if ( LDAP_BACK_QUARANTINE( li ) ) { ldap_back_quarantine( op, rs ); } ldap_pvt_thread_mutex_lock( &li->li_counter_mutex ); ldap_pvt_mp_add( li->li_ops_completed[ SLAP_OP_EXTENDED ], 1 ); ldap_pvt_thread_mutex_unlock( &li->li_counter_mutex ); if ( freedn ) { op->o_tmpfree( dn.bv_val, op->o_tmpmemctx ); op->o_tmpfree( ndn.bv_val, op->o_tmpmemctx ); } /* these have to be freed anyway... */ if ( rs->sr_matched ) { free( (char *)rs->sr_matched ); rs->sr_matched = NULL; } if ( rs->sr_ctrls ) { ldap_controls_free( rs->sr_ctrls ); rs->sr_ctrls = NULL; } if ( text ) { free( text ); rs->sr_text = NULL; } /* in case, cleanup handler */ if ( lc == NULL ) { *lcp = NULL; } return rc; }
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 do_modrdn( Operation *op, SlapReply *rs ) { struct berval dn = BER_BVNULL; struct berval newrdn = BER_BVNULL; struct berval newSuperior = BER_BVNULL; ber_int_t deloldrdn; struct berval pnewSuperior = BER_BVNULL; struct berval nnewSuperior = BER_BVNULL; ber_len_t length; Debug( LDAP_DEBUG_TRACE, "%s do_modrdn\n", op->o_log_prefix, 0, 0 ); /* * Parse the modrdn request. It looks like this: * * ModifyRDNRequest := SEQUENCE { * entry DistinguishedName, * newrdn RelativeDistinguishedName * deleteoldrdn BOOLEAN, * newSuperior [0] LDAPDN OPTIONAL (v3 Only!) * } */ if ( ber_scanf( op->o_ber, "{mmb", &dn, &newrdn, &deloldrdn ) == LBER_ERROR ) { Debug( LDAP_DEBUG_ANY, "%s do_modrdn: ber_scanf failed\n", op->o_log_prefix, 0, 0 ); send_ldap_discon( op, rs, LDAP_PROTOCOL_ERROR, "decoding error" ); return SLAPD_DISCONNECT; } /* Check for newSuperior parameter, if present scan it */ if ( ber_peek_tag( op->o_ber, &length ) == LDAP_TAG_NEWSUPERIOR ) { if ( op->o_protocol < LDAP_VERSION3 ) { /* Connection record indicates v2 but field * newSuperior is present: report error. */ Debug( LDAP_DEBUG_ANY, "%s do_modrdn: newSuperior requires LDAPv3\n", op->o_log_prefix, 0, 0 ); send_ldap_discon( op, rs, LDAP_PROTOCOL_ERROR, "newSuperior requires LDAPv3" ); rs->sr_err = SLAPD_DISCONNECT; goto cleanup; } if ( ber_scanf( op->o_ber, "m", &newSuperior ) == LBER_ERROR ) { Debug( LDAP_DEBUG_ANY, "%s do_modrdn: ber_scanf(\"m\") failed\n", op->o_log_prefix, 0, 0 ); send_ldap_discon( op, rs, LDAP_PROTOCOL_ERROR, "decoding error" ); rs->sr_err = SLAPD_DISCONNECT; goto cleanup; } op->orr_newSup = &pnewSuperior; op->orr_nnewSup = &nnewSuperior; } Debug( LDAP_DEBUG_ARGS, "do_modrdn: dn (%s) newrdn (%s) newsuperior (%s)\n", dn.bv_val, newrdn.bv_val, newSuperior.bv_len ? newSuperior.bv_val : "" ); if ( ber_scanf( op->o_ber, /*{*/ "}") == LBER_ERROR ) { Debug( LDAP_DEBUG_ANY, "%s do_modrdn: ber_scanf failed\n", op->o_log_prefix, 0, 0 ); send_ldap_discon( op, rs, LDAP_PROTOCOL_ERROR, "decoding error" ); rs->sr_err = SLAPD_DISCONNECT; goto cleanup; } if( get_ctrls( op, rs, 1 ) != LDAP_SUCCESS ) { Debug( LDAP_DEBUG_ANY, "%s do_modrdn: get_ctrls failed\n", op->o_log_prefix, 0, 0 ); /* get_ctrls has sent results. Now clean up. */ goto cleanup; } rs->sr_err = dnPrettyNormal( NULL, &dn, &op->o_req_dn, &op->o_req_ndn, op->o_tmpmemctx ); if( rs->sr_err != LDAP_SUCCESS ) { Debug( LDAP_DEBUG_ANY, "%s do_modrdn: invalid dn (%s)\n", op->o_log_prefix, dn.bv_val, 0 ); send_ldap_error( op, rs, LDAP_INVALID_DN_SYNTAX, "invalid DN" ); goto cleanup; } /* FIXME: should have/use rdnPretty / rdnNormalize routines */ rs->sr_err = dnPrettyNormal( NULL, &newrdn, &op->orr_newrdn, &op->orr_nnewrdn, op->o_tmpmemctx ); if( rs->sr_err != LDAP_SUCCESS ) { Debug( LDAP_DEBUG_ANY, "%s do_modrdn: invalid newrdn (%s)\n", op->o_log_prefix, newrdn.bv_val, 0 ); send_ldap_error( op, rs, LDAP_INVALID_DN_SYNTAX, "invalid new RDN" ); goto cleanup; } if( rdn_validate( &op->orr_newrdn ) != LDAP_SUCCESS ) { Debug( LDAP_DEBUG_ANY, "%s do_modrdn: invalid rdn (%s)\n", op->o_log_prefix, op->orr_newrdn.bv_val, 0 ); send_ldap_error( op, rs, LDAP_INVALID_DN_SYNTAX, "invalid new RDN" ); goto cleanup; } if( op->orr_newSup ) { rs->sr_err = dnPrettyNormal( NULL, &newSuperior, &pnewSuperior, &nnewSuperior, op->o_tmpmemctx ); if( rs->sr_err != LDAP_SUCCESS ) { Debug( LDAP_DEBUG_ANY, "%s do_modrdn: invalid newSuperior (%s)\n", op->o_log_prefix, newSuperior.bv_val, 0 ); send_ldap_error( op, rs, LDAP_INVALID_DN_SYNTAX, "invalid newSuperior" ); goto cleanup; } } Statslog( LDAP_DEBUG_STATS, "%s MODRDN dn=\"%s\"\n", op->o_log_prefix, op->o_req_dn.bv_val, 0, 0, 0 ); op->orr_deleteoldrdn = deloldrdn; op->orr_modlist = NULL; /* prepare modlist of modifications from old/new RDN */ rs->sr_err = slap_modrdn2mods( op, rs ); if ( rs->sr_err != LDAP_SUCCESS ) { send_ldap_result( op, rs ); goto cleanup; } op->o_bd = frontendDB; rs->sr_err = frontendDB->be_modrdn( op, rs ); #ifdef LDAP_X_TXN if( rs->sr_err == LDAP_X_TXN_SPECIFY_OKAY ) { /* skip cleanup */ } #endif cleanup: op->o_tmpfree( op->o_req_dn.bv_val, op->o_tmpmemctx ); op->o_tmpfree( op->o_req_ndn.bv_val, op->o_tmpmemctx ); op->o_tmpfree( op->orr_newrdn.bv_val, op->o_tmpmemctx ); op->o_tmpfree( op->orr_nnewrdn.bv_val, op->o_tmpmemctx ); if ( op->orr_modlist != NULL ) slap_mods_free( op->orr_modlist, 1 ); if ( !BER_BVISNULL( &pnewSuperior ) ) { op->o_tmpfree( pnewSuperior.bv_val, op->o_tmpmemctx ); } if ( !BER_BVISNULL( &nnewSuperior ) ) { op->o_tmpfree( nnewSuperior.bv_val, op->o_tmpmemctx ); } return rs->sr_err; }
int do_add( Connection *conn, Operation *op ) { BerElement *ber = op->o_ber; char *last; struct berval dn = { 0, NULL }; ber_len_t len; ber_tag_t tag; Entry *e; Backend *be; Modifications *modlist = NULL; Modifications **modtail = &modlist; Modifications tmp; const char *text; int rc = LDAP_SUCCESS; int manageDSAit; #ifdef LDAP_SLAPI Slapi_PBlock *pb = NULL; #endif /* LDAP_SLAPI */ #ifdef NEW_LOGGING LDAP_LOG( OPERATION, ENTRY, "do_add: conn %d enter\n", conn->c_connid,0,0 ); #else Debug( LDAP_DEBUG_TRACE, "do_add\n", 0, 0, 0 ); #endif /* * Parse the add request. It looks like this: * * AddRequest := [APPLICATION 14] SEQUENCE { * name DistinguishedName, * attrs SEQUENCE OF SEQUENCE { * type AttributeType, * values SET OF AttributeValue * } * } */ /* get the name */ if ( ber_scanf( ber, "{m", /*}*/ &dn ) == LBER_ERROR ) { #ifdef NEW_LOGGING LDAP_LOG( OPERATION, ERR, "do_add: conn %d ber_scanf failed\n", conn->c_connid,0,0 ); #else Debug( LDAP_DEBUG_ANY, "do_add: ber_scanf failed\n", 0, 0, 0 ); #endif send_ldap_disconnect( conn, op, LDAP_PROTOCOL_ERROR, "decoding error" ); return -1; } e = (Entry *) ch_calloc( 1, sizeof(Entry) ); rc = dnPrettyNormal( NULL, &dn, &e->e_name, &e->e_nname ); if( rc != LDAP_SUCCESS ) { #ifdef NEW_LOGGING LDAP_LOG( OPERATION, ERR, "do_add: conn %d invalid dn (%s)\n", conn->c_connid, dn.bv_val, 0 ); #else Debug( LDAP_DEBUG_ANY, "do_add: invalid dn (%s)\n", dn.bv_val, 0, 0 ); #endif send_ldap_result( conn, op, rc = LDAP_INVALID_DN_SYNTAX, NULL, "invalid DN", NULL, NULL ); goto done; } #ifdef NEW_LOGGING LDAP_LOG( OPERATION, ARGS, "do_add: conn %d dn (%s)\n", conn->c_connid, e->e_dn, 0 ); #else Debug( LDAP_DEBUG_ARGS, "do_add: dn (%s)\n", e->e_dn, 0, 0 ); #endif /* get the attrs */ for ( tag = ber_first_element( ber, &len, &last ); tag != LBER_DEFAULT; tag = ber_next_element( ber, &len, last ) ) { Modifications *mod; ber_tag_t rtag; rtag = ber_scanf( ber, "{m{W}}", &tmp.sml_type, &tmp.sml_bvalues ); if ( rtag == LBER_ERROR ) { #ifdef NEW_LOGGING LDAP_LOG( OPERATION, ERR, "do_add: conn %d decoding error \n", conn->c_connid, 0, 0 ); #else Debug( LDAP_DEBUG_ANY, "do_add: decoding error\n", 0, 0, 0 ); #endif send_ldap_disconnect( conn, op, LDAP_PROTOCOL_ERROR, "decoding error" ); rc = -1; goto done; } if ( tmp.sml_bvalues == NULL ) { #ifdef NEW_LOGGING LDAP_LOG( OPERATION, INFO, "do_add: conn %d no values for type %s\n", conn->c_connid, tmp.sml_type.bv_val, 0 ); #else Debug( LDAP_DEBUG_ANY, "no values for type %s\n", tmp.sml_type.bv_val, 0, 0 ); #endif send_ldap_result( conn, op, rc = LDAP_PROTOCOL_ERROR, NULL, "no values for attribute type", NULL, NULL ); goto done; } mod = (Modifications *) ch_malloc( sizeof(Modifications) ); mod->sml_op = LDAP_MOD_ADD; mod->sml_next = NULL; mod->sml_desc = NULL; mod->sml_type = tmp.sml_type; mod->sml_bvalues = tmp.sml_bvalues; *modtail = mod; modtail = &mod->sml_next; } if ( ber_scanf( ber, /*{*/ "}") == LBER_ERROR ) { #ifdef NEW_LOGGING LDAP_LOG( OPERATION, ERR, "do_add: conn %d ber_scanf failed\n", conn->c_connid, 0, 0 ); #else Debug( LDAP_DEBUG_ANY, "do_add: ber_scanf failed\n", 0, 0, 0 ); #endif send_ldap_disconnect( conn, op, LDAP_PROTOCOL_ERROR, "decoding error" ); rc = -1; goto done; } if( (rc = get_ctrls( conn, op, 1 )) != LDAP_SUCCESS ) { #ifdef NEW_LOGGING LDAP_LOG( OPERATION, INFO, "do_add: conn %d get_ctrls failed\n", conn->c_connid, 0, 0 ); #else Debug( LDAP_DEBUG_ANY, "do_add: get_ctrls failed\n", 0, 0, 0 ); #endif goto done; } if ( modlist == NULL ) { send_ldap_result( conn, op, rc = LDAP_PROTOCOL_ERROR, NULL, "no attributes provided", NULL, NULL ); goto done; } Statslog( LDAP_DEBUG_STATS, "conn=%lu op=%lu ADD dn=\"%s\"\n", op->o_connid, op->o_opid, e->e_dn, 0, 0 ); if( e->e_nname.bv_len == 0 ) { /* protocolError may be a more appropriate error */ send_ldap_result( conn, op, rc = LDAP_ALREADY_EXISTS, NULL, "root DSE already exists", NULL, NULL ); goto done; } else if ( bvmatch( &e->e_nname, &global_schemandn ) ) { send_ldap_result( conn, op, rc = LDAP_ALREADY_EXISTS, NULL, "subschema subentry already exists", NULL, NULL ); goto done; } manageDSAit = get_manageDSAit( op ); /* * 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. */ be = select_backend( &e->e_nname, manageDSAit, 0 ); if ( be == NULL ) { BerVarray ref = referral_rewrite( default_referral, NULL, &e->e_name, LDAP_SCOPE_DEFAULT ); if ( ref == NULL ) ref = default_referral; if ( ref != NULL ) { send_ldap_result( conn, op, rc = LDAP_REFERRAL, NULL, NULL, ref, NULL ); if ( ref != default_referral ) ber_bvarray_free( ref ); } else { send_ldap_result( conn, op, rc = LDAP_UNWILLING_TO_PERFORM, NULL, "referral missing", NULL, NULL ); } goto done; } /* check restrictions */ rc = backend_check_restrictions( be, conn, op, NULL, &text ) ; if( rc != LDAP_SUCCESS ) { send_ldap_result( conn, op, rc, NULL, text, NULL, NULL ); goto done; } /* check for referrals */ rc = backend_check_referrals( be, conn, op, &e->e_name, &e->e_nname ); if ( rc != LDAP_SUCCESS ) { goto done; } #ifdef LDAP_SLAPI pb = initAddPlugin( be, conn, op, &dn, e, manageDSAit ); #endif /* LDAP_SLAPI */ /* * do the add if 1 && (2 || 3) * 1) there is an add 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 updatedn. */ if ( be->be_add ) { /* do the update here */ int repl_user = be_isupdate(be, &op->o_ndn ); #ifndef SLAPD_MULTIMASTER if ( !be->be_update_ndn.bv_len || repl_user ) #endif { int update = be->be_update_ndn.bv_len; char textbuf[SLAP_TEXT_BUFLEN]; size_t textlen = sizeof textbuf; rc = slap_mods_check( modlist, update, &text, textbuf, textlen ); if( rc != LDAP_SUCCESS ) { send_ldap_result( conn, op, rc, NULL, text, NULL, NULL ); goto done; } if ( !repl_user ) { for( modtail = &modlist; *modtail != NULL; modtail = &(*modtail)->sml_next ) { assert( (*modtail)->sml_op == LDAP_MOD_ADD ); assert( (*modtail)->sml_desc != NULL ); } rc = slap_mods_opattrs( be, op, modlist, modtail, &text, textbuf, textlen ); if( rc != LDAP_SUCCESS ) { send_ldap_result( conn, op, rc, NULL, text, NULL, NULL ); goto done; } } rc = slap_mods2entry( modlist, &e, repl_user, &text, textbuf, textlen ); if( rc != LDAP_SUCCESS ) { send_ldap_result( conn, op, rc, NULL, text, NULL, NULL ); goto done; } #ifdef LDAP_SLAPI /* * Call the preoperation plugin here, because the entry * will actually contain something. */ rc = doPreAddPluginFNs( be, pb ); if ( rc != LDAP_SUCCESS ) { /* plugin will have sent result */ goto done; } #endif /* LDAP_SLAPI */ if ( (*be->be_add)( be, conn, op, e ) == 0 ) { #ifdef SLAPD_MULTIMASTER if ( !repl_user ) #endif { replog( be, op, &e->e_name, &e->e_nname, e ); } be_entry_release_w( be, conn, op, e ); e = NULL; } #ifndef SLAPD_MULTIMASTER } else { BerVarray defref; BerVarray ref; #ifdef LDAP_SLAPI /* * SLAPI_ADD_ENTRY will be empty, but this may be acceptable * on replicas (for now, it involves the minimum code intrusion). */ rc = doPreAddPluginFNs( be, pb ); if ( rc != LDAP_SUCCESS ) { /* plugin will have sent result */ goto done; } #endif /* LDAP_SLAPI */ defref = be->be_update_refs ? be->be_update_refs : default_referral; if ( defref ) { ref = referral_rewrite( defref, NULL, &e->e_name, LDAP_SCOPE_DEFAULT ); send_ldap_result( conn, op, rc = LDAP_REFERRAL, NULL, NULL, ref ? ref : defref, NULL ); if ( ref ) ber_bvarray_free( ref ); } else { send_ldap_result( conn, op, rc = LDAP_UNWILLING_TO_PERFORM, NULL, "referral missing", NULL, NULL ); } #endif /* SLAPD_MULTIMASTER */ } } else { #ifdef LDAP_SLAPI rc = doPreAddPluginFNs( be, pb ); if ( rc != LDAP_SUCCESS ) { /* plugin will have sent result */ goto done; } #endif #ifdef NEW_LOGGING LDAP_LOG( OPERATION, INFO, "do_add: conn %d no backend support\n", conn->c_connid, 0, 0 ); #else Debug( LDAP_DEBUG_ARGS, " do_add: no backend support\n", 0, 0, 0 ); #endif send_ldap_result( conn, op, rc = LDAP_UNWILLING_TO_PERFORM, NULL, "operation not supported within namingContext", NULL, NULL ); } #ifdef LDAP_SLAPI doPostAddPluginFNs( be, pb ); #endif /* LDAP_SLAPI */ done: if( modlist != NULL ) { slap_mods_free( modlist ); } if( e != NULL ) { entry_free( e ); } return rc; }
int do_bind( Operation *op, SlapReply *rs ) { BerElement *ber = op->o_ber; ber_int_t version; ber_tag_t method; struct berval mech = BER_BVNULL; struct berval dn = BER_BVNULL; ber_tag_t tag; Backend *be = NULL; Debug( LDAP_DEBUG_TRACE, "%s do_bind\n", op->o_log_prefix ); /* * Force the connection to "anonymous" until bind succeeds. */ ldap_pvt_thread_mutex_lock( &op->o_conn->c_mutex ); if ( op->o_conn->c_sasl_bind_in_progress ) { be = op->o_conn->c_authz_backend; } if ( !BER_BVISEMPTY( &op->o_conn->c_dn ) ) { /* log authorization identity demotion */ Statslog( LDAP_DEBUG_STATS, "%s BIND anonymous mech=implicit ssf=0\n", op->o_log_prefix ); } connection2anonymous( op->o_conn ); if ( op->o_conn->c_sasl_bind_in_progress ) { op->o_conn->c_authz_backend = be; } ldap_pvt_thread_mutex_unlock( &op->o_conn->c_mutex ); if ( !BER_BVISNULL( &op->o_dn ) ) { /* NOTE: temporarily wasting few bytes * (until bind is completed), but saving * a couple of ch_free() and ch_strdup("") */ op->o_dn.bv_val[0] = '\0'; op->o_dn.bv_len = 0; } if ( !BER_BVISNULL( &op->o_ndn ) ) { op->o_ndn.bv_val[0] = '\0'; op->o_ndn.bv_len = 0; } /* * Parse the bind request. It looks like this: * * BindRequest ::= SEQUENCE { * version INTEGER, -- version * name DistinguishedName, -- dn * authentication CHOICE { * simple [0] OCTET STRING -- passwd * krbv42ldap [1] OCTET STRING -- OBSOLETE * krbv42dsa [2] OCTET STRING -- OBSOLETE * SASL [3] SaslCredentials * } * } * * SaslCredentials ::= SEQUENCE { * mechanism LDAPString, * credentials OCTET STRING OPTIONAL * } */ tag = ber_scanf( ber, "{imt" /*}*/, &version, &dn, &method ); if ( tag == LBER_ERROR ) { Debug( LDAP_DEBUG_ANY, "%s do_bind: ber_scanf failed\n", op->o_log_prefix ); send_ldap_discon( op, rs, LDAP_PROTOCOL_ERROR, "decoding error" ); rs->sr_err = SLAPD_DISCONNECT; goto cleanup; } op->o_protocol = version; op->orb_method = method; if( op->orb_method != LDAP_AUTH_SASL ) { tag = ber_scanf( ber, /*{*/ "m}", &op->orb_cred ); } else { tag = ber_scanf( ber, "{m" /*}*/, &mech ); if ( tag != LBER_ERROR ) { ber_len_t len; tag = ber_peek_tag( ber, &len ); if ( tag == LDAP_TAG_LDAPCRED ) { tag = ber_scanf( ber, "m", &op->orb_cred ); } else { tag = LDAP_TAG_LDAPCRED; BER_BVZERO( &op->orb_cred ); } if ( tag != LBER_ERROR ) { tag = ber_scanf( ber, /*{{*/ "}}" ); } } } if ( tag == LBER_ERROR ) { Debug( LDAP_DEBUG_ANY, "%s do_bind: ber_scanf failed\n", op->o_log_prefix ); send_ldap_discon( op, rs, LDAP_PROTOCOL_ERROR, "decoding error" ); rs->sr_err = SLAPD_DISCONNECT; goto cleanup; } if( get_ctrls( op, rs, 1 ) != LDAP_SUCCESS ) { Debug( LDAP_DEBUG_ANY, "%s do_bind: get_ctrls failed\n", op->o_log_prefix ); goto cleanup; } /* We use the tmpmemctx here because it speeds up normalization. * However, we must dup with regular malloc when storing any * resulting DNs in the op or conn structures. */ rs->sr_err = dnPrettyNormal( NULL, &dn, &op->o_req_dn, &op->o_req_ndn, op->o_tmpmemctx ); if ( rs->sr_err != LDAP_SUCCESS ) { Debug( LDAP_DEBUG_ANY, "%s do_bind: invalid dn (%s)\n", op->o_log_prefix, dn.bv_val ); send_ldap_error( op, rs, LDAP_INVALID_DN_SYNTAX, "invalid DN" ); goto cleanup; } Statslog( LDAP_DEBUG_STATS, "%s BIND dn=\"%s\" method=%ld\n", op->o_log_prefix, op->o_req_dn.bv_val, (unsigned long) op->orb_method ); if( op->orb_method == LDAP_AUTH_SASL ) { Debug( LDAP_DEBUG_TRACE, "do_bind: dn (%s) SASL mech %s\n", op->o_req_dn.bv_val, mech.bv_val ); } else { Debug( LDAP_DEBUG_TRACE, "do_bind: version=%ld dn=\"%s\" method=%ld\n", (unsigned long) version, op->o_req_dn.bv_val, (unsigned long) op->orb_method ); } if ( version < LDAP_VERSION_MIN || version > LDAP_VERSION_MAX ) { Debug( LDAP_DEBUG_ANY, "%s do_bind: unknown version=%ld\n", op->o_log_prefix, (unsigned long) version ); send_ldap_error( op, rs, LDAP_PROTOCOL_ERROR, "requested protocol version not supported" ); goto cleanup; } else if (!( global_allows & SLAP_ALLOW_BIND_V2 ) && version < LDAP_VERSION3 ) { send_ldap_error( op, rs, LDAP_PROTOCOL_ERROR, "historical protocol version requested, use LDAPv3 instead" ); goto cleanup; } /* * we set connection version regardless of whether bind succeeds or not. */ ldap_pvt_thread_mutex_lock( &op->o_conn->c_mutex ); op->o_conn->c_protocol = version; ldap_pvt_thread_mutex_unlock( &op->o_conn->c_mutex ); op->orb_mech = mech; op->o_bd = frontendDB; rs->sr_err = frontendDB->be_bind( op, rs ); cleanup: if ( rs->sr_err == LDAP_SUCCESS ) { if ( op->orb_method != LDAP_AUTH_SASL ) { ber_dupbv( &op->o_conn->c_authmech, &mech ); } op->o_conn->c_authtype = op->orb_method; } if( !BER_BVISNULL( &op->o_req_dn ) ) { slap_sl_free( op->o_req_dn.bv_val, op->o_tmpmemctx ); BER_BVZERO( &op->o_req_dn ); } if( !BER_BVISNULL( &op->o_req_ndn ) ) { slap_sl_free( op->o_req_ndn.bv_val, op->o_tmpmemctx ); BER_BVZERO( &op->o_req_ndn ); } return rs->sr_err; }
int do_compare( Operation *op, SlapReply *rs ) { struct berval dn = BER_BVNULL; struct berval desc = BER_BVNULL; struct berval value = BER_BVNULL; AttributeAssertion ava = ATTRIBUTEASSERTION_INIT; Debug( LDAP_DEBUG_TRACE, "%s do_compare\n", op->o_log_prefix, 0, 0 ); /* * Parse the compare request. It looks like this: * * CompareRequest := [APPLICATION 14] SEQUENCE { * entry DistinguishedName, * ava SEQUENCE { * type AttributeType, * value AttributeValue * } * } */ if ( ber_scanf( op->o_ber, "{m" /*}*/, &dn ) == LBER_ERROR ) { Debug( LDAP_DEBUG_ANY, "%s do_compare: ber_scanf failed\n", op->o_log_prefix, 0, 0 ); send_ldap_discon( op, rs, LDAP_PROTOCOL_ERROR, "decoding error" ); return SLAPD_DISCONNECT; } if ( ber_scanf( op->o_ber, "{mm}", &desc, &value ) == LBER_ERROR ) { Debug( LDAP_DEBUG_ANY, "%s do_compare: get ava failed\n", op->o_log_prefix, 0, 0 ); send_ldap_discon( op, rs, LDAP_PROTOCOL_ERROR, "decoding error" ); return SLAPD_DISCONNECT; } if ( ber_scanf( op->o_ber, /*{*/ "}" ) == LBER_ERROR ) { Debug( LDAP_DEBUG_ANY, "%s do_compare: ber_scanf failed\n", op->o_log_prefix, 0, 0 ); send_ldap_discon( op, rs, LDAP_PROTOCOL_ERROR, "decoding error" ); return SLAPD_DISCONNECT; } if( get_ctrls( op, rs, 1 ) != LDAP_SUCCESS ) { Debug( LDAP_DEBUG_ANY, "%s do_compare: get_ctrls failed\n", op->o_log_prefix, 0, 0 ); goto cleanup; } rs->sr_err = dnPrettyNormal( NULL, &dn, &op->o_req_dn, &op->o_req_ndn, op->o_tmpmemctx ); if( rs->sr_err != LDAP_SUCCESS ) { Debug( LDAP_DEBUG_ANY, "%s do_compare: invalid dn (%s)\n", op->o_log_prefix, dn.bv_val, 0 ); send_ldap_error( op, rs, LDAP_INVALID_DN_SYNTAX, "invalid DN" ); goto cleanup; } Statslog( LDAP_DEBUG_STATS, "%s CMP dn=\"%s\" attr=\"%s\"\n", op->o_log_prefix, op->o_req_dn.bv_val, desc.bv_val, 0, 0 ); rs->sr_err = slap_bv2ad( &desc, &ava.aa_desc, &rs->sr_text ); if( rs->sr_err != LDAP_SUCCESS ) { rs->sr_err = slap_bv2undef_ad( &desc, &ava.aa_desc, &rs->sr_text, SLAP_AD_PROXIED|SLAP_AD_NOINSERT ); if( rs->sr_err != LDAP_SUCCESS ) { send_ldap_result( op, rs ); goto cleanup; } } rs->sr_err = asserted_value_validate_normalize( ava.aa_desc, ava.aa_desc->ad_type->sat_equality, SLAP_MR_EQUALITY|SLAP_MR_VALUE_OF_ASSERTION_SYNTAX, &value, &ava.aa_value, &rs->sr_text, op->o_tmpmemctx ); if( rs->sr_err != LDAP_SUCCESS ) { send_ldap_result( op, rs ); goto cleanup; } op->orc_ava = &ava; Debug( LDAP_DEBUG_ARGS, "do_compare: dn (%s) attr (%s) value (%s)\n", op->o_req_dn.bv_val, ava.aa_desc->ad_cname.bv_val, ava.aa_value.bv_val ); op->o_bd = frontendDB; rs->sr_err = frontendDB->be_compare( op, rs ); cleanup:; op->o_tmpfree( op->o_req_dn.bv_val, op->o_tmpmemctx ); op->o_tmpfree( op->o_req_ndn.bv_val, op->o_tmpmemctx ); if ( !BER_BVISNULL( &ava.aa_value ) ) { op->o_tmpfree( ava.aa_value.bv_val, op->o_tmpmemctx ); } return rs->sr_err; }
Entry * str2entry2( char *s, int checkvals ) { int rc; Entry *e; struct berval *type, *vals, *nvals; char *freeval; AttributeDescription *ad, *ad_prev; const char *text; char *next; int attr_cnt; int i, lines; Attribute ahead, *atail; /* * LDIF is used as the string format. * An entry looks like this: * * dn: <dn>\n * [<attr>:[:] <value>\n] * [<tab><continuedvalue>\n]* * ... * * If a double colon is used after a type, it means the * following value is encoded as a base 64 string. This * happens if the value contains a non-printing character * or newline. */ Debug( LDAP_DEBUG_TRACE, "=> str2entry: \"%s\"\n", s ? s : "NULL" ); e = entry_alloc(); if( e == NULL ) { Debug( LDAP_DEBUG_ANY, "<= str2entry NULL (entry allocation failed)\n" ); return( NULL ); } /* initialize entry */ e->e_id = NOID; /* dn + attributes */ atail = &ahead; ahead.a_next = NULL; ad = NULL; ad_prev = NULL; attr_cnt = 0; next = s; lines = ldif_countlines( s ); type = ch_calloc( 1, (lines+1)*3*sizeof(struct berval)+lines ); vals = type+lines+1; nvals = vals+lines+1; freeval = (char *)(nvals+lines+1); i = -1; /* parse into individual values, record DN */ while ( (s = ldif_getline( &next )) != NULL ) { int freev; if ( *s == '\n' || *s == '\0' ) { break; } i++; if (i >= lines) { Debug( LDAP_DEBUG_TRACE, "<= str2entry ran past end of entry\n" ); goto fail; } rc = ldif_parse_line2( s, type+i, vals+i, &freev ); freeval[i] = freev; if ( rc ) { Debug( LDAP_DEBUG_TRACE, "<= str2entry NULL (parse_line)\n" ); continue; } if ( bvcasematch( &type[i], &dn_bv ) ) { if ( e->e_dn != NULL ) { Debug( LDAP_DEBUG_ANY, "str2entry: " "entry %ld has multiple DNs \"%s\" and \"%s\"\n", (long) e->e_id, e->e_dn, vals[i].bv_val ); goto fail; } rc = dnPrettyNormal( NULL, &vals[i], &e->e_name, &e->e_nname, NULL ); if( rc != LDAP_SUCCESS ) { Debug( LDAP_DEBUG_ANY, "str2entry: " "entry %ld has invalid DN \"%s\"\n", (long) e->e_id, vals[i].bv_val ); goto fail; } if ( freeval[i] ) free( vals[i].bv_val ); vals[i].bv_val = NULL; i--; continue; } } lines = i+1; /* check to make sure there was a dn: line */ if ( BER_BVISNULL( &e->e_name )) { Debug( LDAP_DEBUG_ANY, "str2entry: entry %ld has no dn\n", (long) e->e_id ); goto fail; } /* Make sure all attributes with multiple values are contiguous */ if ( checkvals ) { int j, k; struct berval bv; int fv; for (i=0; i<lines; i++) { for ( j=i+1; j<lines; j++ ) { if ( bvcasematch( type+i, type+j )) { /* out of order, move intervening attributes down */ if ( j != i+1 ) { bv = vals[j]; fv = freeval[j]; for ( k=j; k>i; k-- ) { type[k] = type[k-1]; vals[k] = vals[k-1]; freeval[k] = freeval[k-1]; } k++; type[k] = type[i]; vals[k] = bv; freeval[k] = fv; } i++; } } } } if ( lines > 0 ) { for ( i=0; i<=lines; i++ ) { ad_prev = ad; if ( !ad || ( i<lines && !bvcasematch( type+i, &ad->ad_cname ))) { ad = NULL; rc = slap_bv2ad( type+i, &ad, &text ); if( rc != LDAP_SUCCESS ) { int wtool = ( slapMode & (SLAP_TOOL_MODE|SLAP_TOOL_READONLY) ) == SLAP_TOOL_MODE; Debug( wtool ? LDAP_DEBUG_ANY : LDAP_DEBUG_TRACE, "<= str2entry: str2ad(%s): %s\n", type[i].bv_val, text ); if( wtool ) { goto fail; } rc = slap_bv2undef_ad( type+i, &ad, &text, 0 ); if( rc != LDAP_SUCCESS ) { Debug( LDAP_DEBUG_ANY, "<= str2entry: slap_str2undef_ad(%s): %s\n", type[i].bv_val, text ); goto fail; } } /* require ';binary' when appropriate (ITS#5071) */ if ( slap_syntax_is_binary( ad->ad_type->sat_syntax ) && !slap_ad_is_binary( ad ) ) { Debug( LDAP_DEBUG_ANY, "str2entry: attributeType %s #%d: " "needs ';binary' transfer as per syntax %s\n", ad->ad_cname.bv_val, 0, ad->ad_type->sat_syntax->ssyn_oid ); goto fail; } } if (( ad_prev && ad != ad_prev ) || ( i == lines )) { int j, k; atail->a_next = attr_alloc( NULL ); atail = atail->a_next; atail->a_flags = 0; atail->a_numvals = attr_cnt; atail->a_desc = ad_prev; atail->a_vals = ch_malloc( (attr_cnt + 1) * sizeof(struct berval)); if( ad_prev->ad_type->sat_equality && ad_prev->ad_type->sat_equality->smr_normalize ) atail->a_nvals = ch_malloc( (attr_cnt + 1) * sizeof(struct berval)); else atail->a_nvals = NULL; k = i - attr_cnt; for ( j=0; j<attr_cnt; j++ ) { if ( freeval[k] ) atail->a_vals[j] = vals[k]; else ber_dupbv( atail->a_vals+j, &vals[k] ); vals[k].bv_val = NULL; if ( atail->a_nvals ) { atail->a_nvals[j] = nvals[k]; nvals[k].bv_val = NULL; } k++; } BER_BVZERO( &atail->a_vals[j] ); if ( atail->a_nvals ) { BER_BVZERO( &atail->a_nvals[j] ); } else { atail->a_nvals = atail->a_vals; } attr_cnt = 0; /* FIXME: we only need this when migrating from an unsorted DB */ if ( atail->a_desc->ad_type->sat_flags & SLAP_AT_SORTED_VAL ) { rc = slap_sort_vals( (Modifications *)atail, &text, &j, NULL ); if ( rc == LDAP_SUCCESS ) { atail->a_flags |= SLAP_ATTR_SORTED_VALS; } else if ( rc == LDAP_TYPE_OR_VALUE_EXISTS ) { Debug( LDAP_DEBUG_ANY, "str2entry: attributeType %s value #%d provided more than once\n", atail->a_desc->ad_cname.bv_val, j ); goto fail; } } if ( i == lines ) break; } if ( BER_BVISNULL( &vals[i] ) ) { Debug( LDAP_DEBUG_ANY, "str2entry: attributeType %s #%d: " "no value\n", ad->ad_cname.bv_val, attr_cnt ); goto fail; } if ( ad->ad_type->sat_equality && ad->ad_type->sat_equality->smr_normalize ) { rc = ordered_value_normalize( SLAP_MR_VALUE_OF_ATTRIBUTE_SYNTAX, ad, ad->ad_type->sat_equality, &vals[i], &nvals[i], NULL ); if ( rc ) { Debug( LDAP_DEBUG_ANY, "<= str2entry NULL (smr_normalize %s %d)\n", ad->ad_cname.bv_val, rc ); goto fail; } } attr_cnt++; } } free( type ); atail->a_next = NULL; e->e_attrs = ahead.a_next; Debug(LDAP_DEBUG_TRACE, "<= str2entry(%s) -> 0x%lx\n", e->e_dn, (unsigned long) e ); return( e ); fail: for ( i=0; i<lines; i++ ) { if ( freeval[i] ) free( vals[i].bv_val ); free( nvals[i].bv_val ); } free( type ); entry_free( e ); return NULL; }
/* * NOTE: the dn must be normalized */ int backsql_dn2id( Operation *op, SlapReply *rs, SQLHDBC dbh, struct berval *ndn, backsql_entryID *id, int matched, int muck ) { backsql_info *bi = op->o_bd->be_private; SQLHSTMT sth = SQL_NULL_HSTMT; BACKSQL_ROW_NTS row = { 0 }; RETCODE rc; int res; struct berval realndn = BER_BVNULL; /* TimesTen */ char upperdn[ BACKSQL_MAX_DN_LEN + 1 ]; struct berval tbbDN; int i, j; /* * NOTE: id can be NULL; in this case, the function * simply checks whether the DN can be successfully * turned into an ID, returning LDAP_SUCCESS for * positive cases, or the most appropriate error */ Debug( LDAP_DEBUG_TRACE, "==>backsql_dn2id(\"%s\")%s%s\n", ndn->bv_val, id == NULL ? " (no ID expected)" : "", matched ? " matched expected" : "" ); if ( id ) { /* NOTE: trap inconsistencies */ assert( BER_BVISNULL( &id->eid_ndn ) ); } if ( ndn->bv_len > BACKSQL_MAX_DN_LEN ) { Debug( LDAP_DEBUG_TRACE, " backsql_dn2id(\"%s\"): DN length=%ld " "exceeds max DN length %d:\n", ndn->bv_val, ndn->bv_len, BACKSQL_MAX_DN_LEN ); return LDAP_OTHER; } /* return baseObject if available and matches */ /* FIXME: if ndn is already mucked, we cannot check this */ if ( bi->sql_baseObject != NULL && dn_match( ndn, &bi->sql_baseObject->e_nname ) ) { if ( id != NULL ) { #ifdef BACKSQL_ARBITRARY_KEY ber_dupbv_x( &id->eid_id, &backsql_baseObject_bv, op->o_tmpmemctx ); ber_dupbv_x( &id->eid_keyval, &backsql_baseObject_bv, op->o_tmpmemctx ); #else /* ! BACKSQL_ARBITRARY_KEY */ id->eid_id = BACKSQL_BASEOBJECT_ID; id->eid_keyval = BACKSQL_BASEOBJECT_KEYVAL; #endif /* ! BACKSQL_ARBITRARY_KEY */ id->eid_oc_id = BACKSQL_BASEOBJECT_OC; ber_dupbv_x( &id->eid_ndn, &bi->sql_baseObject->e_nname, op->o_tmpmemctx ); ber_dupbv_x( &id->eid_dn, &bi->sql_baseObject->e_name, op->o_tmpmemctx ); id->eid_next = NULL; } return LDAP_SUCCESS; } /* begin TimesTen */ Debug( LDAP_DEBUG_TRACE, " backsql_dn2id(\"%s\"): id_query \"%s\"\n", ndn->bv_val, bi->sql_id_query, 0 ); assert( bi->sql_id_query != NULL ); rc = backsql_Prepare( dbh, &sth, bi->sql_id_query, 0 ); if ( rc != SQL_SUCCESS ) { Debug( LDAP_DEBUG_TRACE, " backsql_dn2id(\"%s\"): " "error preparing SQL:\n %s", ndn->bv_val, bi->sql_id_query, 0 ); backsql_PrintErrors( bi->sql_db_env, dbh, sth, rc ); res = LDAP_OTHER; goto done; } realndn = *ndn; if ( muck ) { if ( backsql_api_dn2odbc( op, rs, &realndn ) ) { Debug( LDAP_DEBUG_TRACE, " backsql_dn2id(\"%s\"): " "backsql_api_dn2odbc(\"%s\") failed\n", ndn->bv_val, realndn.bv_val, 0 ); res = LDAP_OTHER; goto done; } } if ( BACKSQL_HAS_LDAPINFO_DN_RU( bi ) ) { /* * Prepare an upper cased, byte reversed version * that can be searched using indexes */ for ( i = 0, j = realndn.bv_len - 1; realndn.bv_val[ i ]; i++, j--) { upperdn[ i ] = realndn.bv_val[ j ]; } upperdn[ i ] = '\0'; ldap_pvt_str2upper( upperdn ); Debug( LDAP_DEBUG_TRACE, " backsql_dn2id(\"%s\"): " "upperdn=\"%s\"\n", ndn->bv_val, upperdn, 0 ); ber_str2bv( upperdn, 0, 0, &tbbDN ); } else { if ( BACKSQL_USE_REVERSE_DN( bi ) ) { AC_MEMCPY( upperdn, realndn.bv_val, realndn.bv_len + 1 ); ldap_pvt_str2upper( upperdn ); Debug( LDAP_DEBUG_TRACE, " backsql_dn2id(\"%s\"): " "upperdn=\"%s\"\n", ndn->bv_val, upperdn, 0 ); ber_str2bv( upperdn, 0, 0, &tbbDN ); } else { tbbDN = realndn; } } rc = backsql_BindParamBerVal( sth, 1, SQL_PARAM_INPUT, &tbbDN ); if ( rc != SQL_SUCCESS) { /* end TimesTen */ Debug( LDAP_DEBUG_TRACE, " backsql_dn2id(\"%s\"): " "error binding dn=\"%s\" parameter:\n", ndn->bv_val, tbbDN.bv_val, 0 ); backsql_PrintErrors( bi->sql_db_env, dbh, sth, rc ); res = LDAP_OTHER; goto done; } rc = SQLExecute( sth ); if ( rc != SQL_SUCCESS ) { Debug( LDAP_DEBUG_TRACE, " backsql_dn2id(\"%s\"): " "error executing query (\"%s\", \"%s\"):\n", ndn->bv_val, bi->sql_id_query, tbbDN.bv_val ); backsql_PrintErrors( bi->sql_db_env, dbh, sth, rc ); res = LDAP_OTHER; goto done; } backsql_BindRowAsStrings_x( sth, &row, op->o_tmpmemctx ); rc = SQLFetch( sth ); if ( BACKSQL_SUCCESS( rc ) ) { char buf[ SLAP_TEXT_BUFLEN ]; #ifdef LDAP_DEBUG snprintf( buf, sizeof(buf), "id=%s keyval=%s oc_id=%s dn=%s", row.cols[ 0 ], row.cols[ 1 ], row.cols[ 2 ], row.cols[ 3 ] ); Debug( LDAP_DEBUG_TRACE, " backsql_dn2id(\"%s\"): %s\n", ndn->bv_val, buf, 0 ); #endif /* LDAP_DEBUG */ res = LDAP_SUCCESS; if ( id != NULL ) { struct berval dn; id->eid_next = NULL; #ifdef BACKSQL_ARBITRARY_KEY ber_str2bv_x( row.cols[ 0 ], 0, 1, &id->eid_id, op->o_tmpmemctx ); ber_str2bv_x( row.cols[ 1 ], 0, 1, &id->eid_keyval, op->o_tmpmemctx ); #else /* ! BACKSQL_ARBITRARY_KEY */ if ( lutil_atoulx( &id->eid_id, row.cols[ 0 ], 0 ) != 0 ) { res = LDAP_OTHER; goto done; } if ( lutil_atoulx( &id->eid_keyval, row.cols[ 1 ], 0 ) != 0 ) { res = LDAP_OTHER; goto done; } #endif /* ! BACKSQL_ARBITRARY_KEY */ if ( lutil_atoulx( &id->eid_oc_id, row.cols[ 2 ], 0 ) != 0 ) { res = LDAP_OTHER; goto done; } ber_str2bv( row.cols[ 3 ], 0, 0, &dn ); if ( backsql_api_odbc2dn( op, rs, &dn ) ) { res = LDAP_OTHER; goto done; } res = dnPrettyNormal( NULL, &dn, &id->eid_dn, &id->eid_ndn, op->o_tmpmemctx ); if ( res != LDAP_SUCCESS ) { Debug( LDAP_DEBUG_TRACE, " backsql_dn2id(\"%s\"): " "dnPrettyNormal failed (%d: %s)\n", realndn.bv_val, res, ldap_err2string( res ) ); /* cleanup... */ (void)backsql_free_entryID( id, 0, op->o_tmpmemctx ); } if ( dn.bv_val != row.cols[ 3 ] ) { free( dn.bv_val ); } } } else { res = LDAP_NO_SUCH_OBJECT; if ( matched ) { struct berval pdn = *ndn; /* * Look for matched */ rs->sr_matched = NULL; while ( !be_issuffix( op->o_bd, &pdn ) ) { char *matchedDN = NULL; dnParent( &pdn, &pdn ); /* * Empty DN ("") defaults to LDAP_SUCCESS */ rs->sr_err = backsql_dn2id( op, rs, dbh, &pdn, id, 0, 1 ); switch ( rs->sr_err ) { case LDAP_NO_SUCH_OBJECT: /* try another one */ break; case LDAP_SUCCESS: matchedDN = pdn.bv_val; /* fail over to next case */ default: rs->sr_err = LDAP_NO_SUCH_OBJECT; rs->sr_matched = matchedDN; goto done; } } } } done:; backsql_FreeRow_x( &row, op->o_tmpmemctx ); Debug( LDAP_DEBUG_TRACE, "<==backsql_dn2id(\"%s\"): err=%d\n", ndn->bv_val, res, 0 ); if ( sth != SQL_NULL_HSTMT ) { SQLFreeStmt( sth, SQL_DROP ); } if ( !BER_BVISNULL( &realndn ) && realndn.bv_val != ndn->bv_val ) { ch_free( realndn.bv_val ); } return res; }
/* ** Adds a group to the internal list from the passed entry. ** scan specifies whether to add all maching members to the group. ** modify specifies whether to modify the given group entry (when modify == 0), ** or to modify the group entry in the database (when modify == 1 and e = NULL and ndn != NULL). ** agi - pointer to the groups and the attribute definitions ** agd - the attribute definition of the added group ** e - the entry representing the group, can be NULL if the ndn is specified, and modify == 1 ** ndn - the DN of the group, can be NULL if we give a non-NULL e */ static int autogroup_add_group( Operation *op, autogroup_info_t *agi, autogroup_def_t *agd, Entry *e, BerValue *ndn, int scan, int modify) { autogroup_entry_t **agep = &agi->agi_entry; autogroup_filter_t *agf, *agf_prev = NULL; slap_overinst *on = (slap_overinst *)op->o_bd->bd_info; LDAPURLDesc *lud = NULL; Attribute *a; BerValue *bv, dn; int rc = 0, match = 1, null_entry = 0; if ( e == NULL ) { if ( overlay_entry_get_ov( op, ndn, NULL, NULL, 0, &e, on ) != LDAP_SUCCESS || e == NULL ) { Debug( LDAP_DEBUG_TRACE, "autogroup_add_group: cannot get entry for <%s>\n", ndn->bv_val, 0, 0); return 1; } null_entry = 1; } Debug(LDAP_DEBUG_TRACE, "==> autogroup_add_group <%s>\n", e->e_name.bv_val, 0, 0); if ( agi->agi_entry != NULL ) { for ( ; *agep ; agep = &(*agep)->age_next ) { dnMatch( &match, 0, NULL, NULL, &e->e_nname, &(*agep)->age_ndn ); if ( match == 0 ) { Debug( LDAP_DEBUG_TRACE, "autogroup_add_group: group already exists: <%s>\n", e->e_name.bv_val,0,0); return 1; } /* goto last */; } } *agep = (autogroup_entry_t *)ch_calloc( 1, sizeof( autogroup_entry_t ) ); ldap_pvt_thread_mutex_init( &(*agep)->age_mutex ); (*agep)->age_def = agd; (*agep)->age_filter = NULL; ber_dupbv( &(*agep)->age_dn, &e->e_name ); ber_dupbv( &(*agep)->age_ndn, &e->e_nname ); a = attrs_find( e->e_attrs, agd->agd_member_url_ad ); if ( null_entry == 1 ) { a = attrs_dup( a ); overlay_entry_release_ov( op, e, 0, on ); } if( a == NULL ) { Debug( LDAP_DEBUG_TRACE, "autogroup_add_group: group has no memberURL\n", 0,0,0); } else { for ( bv = a->a_nvals; !BER_BVISNULL( bv ); bv++ ) { agf = (autogroup_filter_t*)ch_calloc( 1, sizeof( autogroup_filter_t ) ); if ( ldap_url_parse( bv->bv_val, &lud ) != LDAP_URL_SUCCESS ) { Debug( LDAP_DEBUG_TRACE, "autogroup_add_group: cannot parse url <%s>\n", bv->bv_val,0,0); /* FIXME: error? */ ch_free( agf ); continue; } agf->agf_scope = lud->lud_scope; if ( lud->lud_dn == NULL ) { BER_BVSTR( &dn, "" ); } else { ber_str2bv( lud->lud_dn, 0, 0, &dn ); } rc = dnPrettyNormal( NULL, &dn, &agf->agf_dn, &agf->agf_ndn, NULL ); if ( rc != LDAP_SUCCESS ) { Debug( LDAP_DEBUG_TRACE, "autogroup_add_group: cannot normalize DN <%s>\n", dn.bv_val,0,0); /* FIXME: error? */ goto cleanup; } if ( lud->lud_filter != NULL ) { ber_str2bv( lud->lud_filter, 0, 1, &agf->agf_filterstr); agf->agf_filter = str2filter( lud->lud_filter ); } agf->agf_next = NULL; if( (*agep)->age_filter == NULL ) { (*agep)->age_filter = agf; } if( agf_prev != NULL ) { agf_prev->agf_next = agf; } agf_prev = agf; if ( scan == 1 ){ autogroup_add_members_from_filter( op, e, (*agep), agf, modify ); } Debug( LDAP_DEBUG_TRACE, "autogroup_add_group: added memberURL DN <%s> with filter <%s>\n", agf->agf_ndn.bv_val, agf->agf_filterstr.bv_val, 0); ldap_free_urldesc( lud ); continue; cleanup:; ldap_free_urldesc( lud ); ch_free( agf ); } } if ( null_entry == 1 ) { attrs_free( a ); } return rc; }
static int ldap_build_entry( Operation *op, LDAPMessage *e, Entry *ent, struct berval *bdn ) { struct berval a; BerElement ber = *ldap_get_message_ber( e ); Attribute *attr, **attrp; const char *text; int last; char *lastb; ber_len_t len; /* safe assumptions ... */ assert( ent != NULL ); BER_BVZERO( &ent->e_bv ); if ( ber_scanf( &ber, "{m", bdn ) == LBER_ERROR ) { return LDAP_DECODING_ERROR; } /* * 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? */ /* Note: if the distinguished values or the naming attributes * change, should we massage them as well? */ if ( dnPrettyNormal( NULL, bdn, &ent->e_name, &ent->e_nname, op->o_tmpmemctx ) != LDAP_SUCCESS ) { return LDAP_INVALID_DN_SYNTAX; } ent->e_attrs = NULL; if ( ber_first_element( &ber, &len, &lastb ) != LBER_SEQUENCE ) { return LDAP_SUCCESS; } attrp = &ent->e_attrs; while ( ber_next_element( &ber, &len, lastb ) == LBER_SEQUENCE && ber_scanf( &ber, "{m", &a ) != LBER_ERROR ) { int i; slap_syntax_validate_func *validate; slap_syntax_transform_func *pretty; attr = attr_alloc( NULL ); if ( attr == NULL ) { return LDAP_OTHER; } 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 ldap_build_entry: " "slap_bv2undef_ad(%s): %s\n", op->o_log_prefix, a.bv_val, text ); ( void )ber_scanf( &ber, "x" /* [W] */ ); attr_free( attr ); continue; } } /* 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] */ ); attr_free( attr ); continue; } if ( ber_scanf( &ber, "[W]", &attr->a_vals ) == LBER_ERROR || attr->a_vals == NULL ) { /* * Note: attr->a_vals can be null when using * values result filter */ attr->a_vals = (struct berval *)&slap_dummy_bv; } validate = attr->a_desc->ad_type->sat_syntax->ssyn_validate; pretty = attr->a_desc->ad_type->sat_syntax->ssyn_pretty; if ( !validate && !pretty ) { attr->a_nvals = NULL; attr_free( attr ); goto next_attr; } for ( i = 0; !BER_BVISNULL( &attr->a_vals[i] ); i++ ) ; last = i; /* * check that each value is valid per syntax * and pretty if appropriate */ 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, NULL ); } else { rc = ordered_value_validate( attr->a_desc, &attr->a_vals[i], 0 ); } if ( rc != LDAP_SUCCESS ) { ObjectClass *oc; /* check if, by chance, it's an undefined objectClass */ if ( attr->a_desc == slap_schema.si_ad_objectClass && ( oc = oc_bvfind_undef( &attr->a_vals[i] ) ) != NULL ) { ber_dupbv( &pval, &oc->soc_cname ); rc = LDAP_SUCCESS; } else { ber_memfree( attr->a_vals[i].bv_val ); 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--; } } if ( rc == LDAP_SUCCESS && pretty ) { ber_memfree( attr->a_vals[i].bv_val ); attr->a_vals[i] = pval; } } attr->a_numvals = last = i; if ( last == 0 && attr->a_vals != &slap_dummy_bv ) { attr->a_nvals = NULL; attr_free( attr ); goto next_attr; } if ( last && attr->a_desc->ad_type->sat_equality && attr->a_desc->ad_type->sat_equality->smr_normalize ) { attr->a_nvals = ch_malloc( ( last + 1 )*sizeof( struct berval ) ); for ( i = 0; i < last; i++ ) { int rc; rc = 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], NULL ); if ( rc != LDAP_SUCCESS ) { ber_memfree( attr->a_vals[i].bv_val ); 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 ) { attr_free( attr ); goto next_attr; } } else { attr->a_nvals = attr->a_vals; } attr->a_numvals = last; /* Handle sorted vals, strip dups but keep the attr */ if ( attr->a_desc->ad_type->sat_flags & SLAP_AT_SORTED_VAL ) { while ( attr->a_numvals > 1 ) { 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( attr->a_nvals[i].bv_val ); ber_memfree( attr->a_vals[i].bv_val ); attr->a_numvals--; assert( i >= 0 ); 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; } *attrp = attr; attrp = &attr->a_next; next_attr:; } return LDAP_SUCCESS; }
static int rc_cf_gen( ConfigArgs *c ) { slap_overinst *on = (slap_overinst *)c->bi; retcode_t *rd = (retcode_t *)on->on_bi.bi_private; int rc = ARG_BAD_CONF; if ( c->op == SLAP_CONFIG_EMIT ) { switch( c->type ) { case RC_PARENT: if ( !BER_BVISEMPTY( &rd->rd_pdn )) { rc = value_add_one( &c->rvalue_vals, &rd->rd_pdn ); if ( rc == 0 ) { rc = value_add_one( &c->rvalue_nvals, &rd->rd_npdn ); } return rc; } rc = 0; break; case RC_ITEM: { retcode_item_t *rdi; int i; for ( rdi = rd->rd_item, i = 0; rdi; rdi = rdi->rdi_next, i++ ) { char buf[4096]; struct berval bv; char *ptr; bv.bv_len = snprintf( buf, sizeof( buf ), SLAP_X_ORDERED_FMT, i ); bv.bv_len += rdi->rdi_line.bv_len; ptr = bv.bv_val = ch_malloc( bv.bv_len + 1 ); ptr = lutil_strcopy( ptr, buf ); ptr = lutil_strncopy( ptr, rdi->rdi_line.bv_val, rdi->rdi_line.bv_len ); ber_bvarray_add( &c->rvalue_vals, &bv ); } rc = 0; } break; default: LDAP_BUG(); break; } return rc; } else if ( c->op == LDAP_MOD_DELETE ) { switch( c->type ) { case RC_PARENT: if ( rd->rd_pdn.bv_val ) { ber_memfree ( rd->rd_pdn.bv_val ); rc = 0; } if ( rd->rd_npdn.bv_val ) { ber_memfree ( rd->rd_npdn.bv_val ); } break; case RC_ITEM: if ( c->valx == -1 ) { retcode_item_t *rdi, *next; for ( rdi = rd->rd_item; rdi != NULL; rdi = next ) { next = rdi->rdi_next; retcode_item_destroy( rdi ); } } else { retcode_item_t **rdip, *rdi; int i; for ( rdip = &rd->rd_item, i = 0; i <= c->valx && *rdip; i++, rdip = &(*rdip)->rdi_next ) ; if ( *rdip == NULL ) { return 1; } rdi = *rdip; *rdip = rdi->rdi_next; retcode_item_destroy( rdi ); } rc = 0; break; default: LDAP_BUG(); break; } return rc; /* FIXME */ } switch( c->type ) { case RC_PARENT: if ( rd->rd_pdn.bv_val ) { ber_memfree ( rd->rd_pdn.bv_val ); } if ( rd->rd_npdn.bv_val ) { ber_memfree ( rd->rd_npdn.bv_val ); } rd->rd_pdn = c->value_dn; rd->rd_npdn = c->value_ndn; rc = 0; break; case RC_ITEM: { retcode_item_t rdi = { BER_BVNULL }, **rdip; struct berval bv, rdn, nrdn; char *next = NULL; int i; if ( c->argc < 3 ) { snprintf( c->cr_msg, sizeof(c->cr_msg), "\"retcode-item <RDN> <retcode> [<text>]\": " "missing args" ); Debug( LDAP_DEBUG_CONFIG, "%s: retcode: %s\n", c->log, c->cr_msg ); return ARG_BAD_CONF; } ber_str2bv( c->argv[ 1 ], 0, 0, &bv ); rc = dnPrettyNormal( NULL, &bv, &rdn, &nrdn, NULL ); if ( rc != LDAP_SUCCESS ) { snprintf( c->cr_msg, sizeof(c->cr_msg), "unable to normalize RDN \"%s\": %d", c->argv[ 1 ], rc ); Debug( LDAP_DEBUG_CONFIG, "%s: retcode: %s\n", c->log, c->cr_msg ); return ARG_BAD_CONF; } if ( !dnIsOneLevelRDN( &nrdn ) ) { snprintf( c->cr_msg, sizeof(c->cr_msg), "value \"%s\" is not a RDN", c->argv[ 1 ] ); Debug( LDAP_DEBUG_CONFIG, "%s: retcode: %s\n", c->log, c->cr_msg ); return ARG_BAD_CONF; } if ( BER_BVISNULL( &rd->rd_npdn ) ) { /* FIXME: we use the database suffix */ if ( c->be->be_nsuffix == NULL ) { snprintf( c->cr_msg, sizeof(c->cr_msg), "either \"retcode-parent\" " "or \"suffix\" must be defined" ); Debug( LDAP_DEBUG_CONFIG, "%s: retcode: %s\n", c->log, c->cr_msg ); return ARG_BAD_CONF; } ber_dupbv( &rd->rd_pdn, &c->be->be_suffix[ 0 ] ); ber_dupbv( &rd->rd_npdn, &c->be->be_nsuffix[ 0 ] ); } build_new_dn( &rdi.rdi_dn, &rd->rd_pdn, &rdn, NULL ); build_new_dn( &rdi.rdi_ndn, &rd->rd_npdn, &nrdn, NULL ); ch_free( rdn.bv_val ); ch_free( nrdn.bv_val ); rdi.rdi_err = strtol( c->argv[ 2 ], &next, 0 ); if ( next == c->argv[ 2 ] || next[ 0 ] != '\0' ) { snprintf( c->cr_msg, sizeof(c->cr_msg), "unable to parse return code \"%s\"", c->argv[ 2 ] ); Debug( LDAP_DEBUG_CONFIG, "%s: retcode: %s\n", c->log, c->cr_msg ); return ARG_BAD_CONF; } rdi.rdi_mask = SN_DG_OP_ALL; if ( c->argc > 3 ) { for ( i = 3; i < c->argc; i++ ) { if ( strncasecmp( c->argv[ i ], "op=", STRLENOF( "op=" ) ) == 0 ) { char **ops; int j; ops = ldap_str2charray( &c->argv[ i ][ STRLENOF( "op=" ) ], "," ); assert( ops != NULL ); rdi.rdi_mask = SN_DG_OP_NONE; for ( j = 0; ops[ j ] != NULL; j++ ) { if ( strcasecmp( ops[ j ], "add" ) == 0 ) { rdi.rdi_mask |= SN_DG_OP_ADD; } else if ( strcasecmp( ops[ j ], "bind" ) == 0 ) { rdi.rdi_mask |= SN_DG_OP_BIND; } else if ( strcasecmp( ops[ j ], "compare" ) == 0 ) { rdi.rdi_mask |= SN_DG_OP_COMPARE; } else if ( strcasecmp( ops[ j ], "delete" ) == 0 ) { rdi.rdi_mask |= SN_DG_OP_DELETE; } else if ( strcasecmp( ops[ j ], "modify" ) == 0 ) { rdi.rdi_mask |= SN_DG_OP_MODIFY; } else if ( strcasecmp( ops[ j ], "rename" ) == 0 || strcasecmp( ops[ j ], "modrdn" ) == 0 ) { rdi.rdi_mask |= SN_DG_OP_RENAME; } else if ( strcasecmp( ops[ j ], "search" ) == 0 ) { rdi.rdi_mask |= SN_DG_OP_SEARCH; } else if ( strcasecmp( ops[ j ], "extended" ) == 0 ) { rdi.rdi_mask |= SN_DG_EXTENDED; } else if ( strcasecmp( ops[ j ], "auth" ) == 0 ) { rdi.rdi_mask |= SN_DG_OP_AUTH; } else if ( strcasecmp( ops[ j ], "read" ) == 0 ) { rdi.rdi_mask |= SN_DG_OP_READ; } else if ( strcasecmp( ops[ j ], "write" ) == 0 ) { rdi.rdi_mask |= SN_DG_OP_WRITE; } else if ( strcasecmp( ops[ j ], "all" ) == 0 ) { rdi.rdi_mask |= SN_DG_OP_ALL; } else { snprintf( c->cr_msg, sizeof(c->cr_msg), "unknown op \"%s\"", ops[ j ] ); ldap_charray_free( ops ); Debug( LDAP_DEBUG_CONFIG, "%s: retcode: %s\n", c->log, c->cr_msg ); return ARG_BAD_CONF; } } ldap_charray_free( ops ); } else if ( strncasecmp( c->argv[ i ], "text=", STRLENOF( "text=" ) ) == 0 ) { if ( !BER_BVISNULL( &rdi.rdi_text ) ) { snprintf( c->cr_msg, sizeof(c->cr_msg), "\"text\" already provided" ); Debug( LDAP_DEBUG_CONFIG, "%s: retcode: %s\n", c->log, c->cr_msg ); return ARG_BAD_CONF; } ber_str2bv( &c->argv[ i ][ STRLENOF( "text=" ) ], 0, 1, &rdi.rdi_text ); } else if ( strncasecmp( c->argv[ i ], "matched=", STRLENOF( "matched=" ) ) == 0 ) { struct berval dn; if ( !BER_BVISNULL( &rdi.rdi_matched ) ) { snprintf( c->cr_msg, sizeof(c->cr_msg), "\"matched\" already provided" ); Debug( LDAP_DEBUG_CONFIG, "%s: retcode: %s\n", c->log, c->cr_msg ); return ARG_BAD_CONF; } ber_str2bv( &c->argv[ i ][ STRLENOF( "matched=" ) ], 0, 0, &dn ); if ( dnPretty( NULL, &dn, &rdi.rdi_matched, NULL ) != LDAP_SUCCESS ) { snprintf( c->cr_msg, sizeof(c->cr_msg), "unable to prettify matched DN \"%s\"", &c->argv[ i ][ STRLENOF( "matched=" ) ] ); Debug( LDAP_DEBUG_CONFIG, "%s: retcode: %s\n", c->log, c->cr_msg ); return ARG_BAD_CONF; } } else if ( strncasecmp( c->argv[ i ], "ref=", STRLENOF( "ref=" ) ) == 0 ) { char **refs; int j; if ( rdi.rdi_ref != NULL ) { snprintf( c->cr_msg, sizeof(c->cr_msg), "\"ref\" already provided" ); Debug( LDAP_DEBUG_CONFIG, "%s: retcode: %s\n", c->log, c->cr_msg ); return ARG_BAD_CONF; } if ( rdi.rdi_err != LDAP_REFERRAL ) { snprintf( c->cr_msg, sizeof(c->cr_msg), "providing \"ref\" " "along with a non-referral " "resultCode may cause slapd failures " "related to internal checks" ); Debug( LDAP_DEBUG_CONFIG, "%s: retcode: %s\n", c->log, c->cr_msg ); } refs = ldap_str2charray( &c->argv[ i ][ STRLENOF( "ref=" ) ], " " ); assert( refs != NULL ); for ( j = 0; refs[ j ] != NULL; j++ ) { struct berval bv; ber_str2bv( refs[ j ], 0, 1, &bv ); ber_bvarray_add( &rdi.rdi_ref, &bv ); } ldap_charray_free( refs ); } else if ( strncasecmp( c->argv[ i ], "sleeptime=", STRLENOF( "sleeptime=" ) ) == 0 ) { if ( rdi.rdi_sleeptime != 0 ) { snprintf( c->cr_msg, sizeof(c->cr_msg), "\"sleeptime\" already provided" ); Debug( LDAP_DEBUG_CONFIG, "%s: retcode: %s\n", c->log, c->cr_msg ); return ARG_BAD_CONF; } if ( lutil_atoi( &rdi.rdi_sleeptime, &c->argv[ i ][ STRLENOF( "sleeptime=" ) ] ) ) { snprintf( c->cr_msg, sizeof(c->cr_msg), "unable to parse \"sleeptime=%s\"", &c->argv[ i ][ STRLENOF( "sleeptime=" ) ] ); Debug( LDAP_DEBUG_CONFIG, "%s: retcode: %s\n", c->log, c->cr_msg ); return ARG_BAD_CONF; } } else if ( strncasecmp( c->argv[ i ], "unsolicited=", STRLENOF( "unsolicited=" ) ) == 0 ) { char *data; if ( !BER_BVISNULL( &rdi.rdi_unsolicited_oid ) ) { snprintf( c->cr_msg, sizeof(c->cr_msg), "\"unsolicited\" already provided" ); Debug( LDAP_DEBUG_CONFIG, "%s: retcode: %s\n", c->log, c->cr_msg ); return ARG_BAD_CONF; } data = strchr( &c->argv[ i ][ STRLENOF( "unsolicited=" ) ], ':' ); if ( data != NULL ) { struct berval oid; if ( ldif_parse_line2( &c->argv[ i ][ STRLENOF( "unsolicited=" ) ], &oid, &rdi.rdi_unsolicited_data, NULL ) ) { snprintf( c->cr_msg, sizeof(c->cr_msg), "unable to parse \"unsolicited\"" ); Debug( LDAP_DEBUG_CONFIG, "%s: retcode: %s\n", c->log, c->cr_msg ); return ARG_BAD_CONF; } ber_dupbv( &rdi.rdi_unsolicited_oid, &oid ); } else { ber_str2bv( &c->argv[ i ][ STRLENOF( "unsolicited=" ) ], 0, 1, &rdi.rdi_unsolicited_oid ); } } else if ( strncasecmp( c->argv[ i ], "flags=", STRLENOF( "flags=" ) ) == 0 ) { char *arg = &c->argv[ i ][ STRLENOF( "flags=" ) ]; if ( strcasecmp( arg, "disconnect" ) == 0 ) { rdi.rdi_flags |= RDI_PRE_DISCONNECT; } else if ( strcasecmp( arg, "pre-disconnect" ) == 0 ) { rdi.rdi_flags |= RDI_PRE_DISCONNECT; } else if ( strcasecmp( arg, "post-disconnect" ) == 0 ) { rdi.rdi_flags |= RDI_POST_DISCONNECT; } else { snprintf( c->cr_msg, sizeof(c->cr_msg), "unknown flag \"%s\"", arg ); Debug( LDAP_DEBUG_CONFIG, "%s: retcode: %s\n", c->log, c->cr_msg ); return ARG_BAD_CONF; } } else { snprintf( c->cr_msg, sizeof(c->cr_msg), "unknown option \"%s\"", c->argv[ i ] ); Debug( LDAP_DEBUG_CONFIG, "%s: retcode: %s\n", c->log, c->cr_msg ); return ARG_BAD_CONF; } } } rdi.rdi_line.bv_len = 2*(c->argc - 1) + c->argc - 2; for ( i = 1; i < c->argc; i++ ) { rdi.rdi_line.bv_len += strlen( c->argv[ i ] ); } next = rdi.rdi_line.bv_val = ch_malloc( rdi.rdi_line.bv_len + 1 ); for ( i = 1; i < c->argc; i++ ) { *next++ = '"'; next = lutil_strcopy( next, c->argv[ i ] ); *next++ = '"'; *next++ = ' '; } *--next = '\0'; for ( rdip = &rd->rd_item; *rdip; rdip = &(*rdip)->rdi_next ) /* go to last */ ; *rdip = ( retcode_item_t * )ch_malloc( sizeof( retcode_item_t ) ); *(*rdip) = rdi; rc = 0; } break; default: rc = SLAP_CONF_UNKNOWN; break; } return rc; }
static int dynlist_prepare_entry( Operation *op, SlapReply *rs, dynlist_info_t *dli ) { Attribute *a, *id = NULL; slap_callback cb = { 0 }; Operation o = *op; struct berval *url; Entry *e; int opattrs, userattrs; dynlist_sc_t dlc = { 0 }; dynlist_map_t *dlm; a = attrs_find( rs->sr_entry->e_attrs, dli->dli_ad ); if ( a == NULL ) { /* FIXME: error? */ return SLAP_CB_CONTINUE; } opattrs = SLAP_OPATTRS( rs->sr_attr_flags ); userattrs = SLAP_USERATTRS( rs->sr_attr_flags ); /* Don't generate member list if it wasn't requested */ for ( dlm = dli->dli_dlm; dlm; dlm = dlm->dlm_next ) { AttributeDescription *ad = dlm->dlm_mapped_ad ? dlm->dlm_mapped_ad : dlm->dlm_member_ad; if ( userattrs || ad_inlist( ad, rs->sr_attrs ) ) break; } if ( dli->dli_dlm && !dlm ) return SLAP_CB_CONTINUE; if ( ad_dgIdentity && ( id = attrs_find( rs->sr_entry->e_attrs, ad_dgIdentity ))) { Attribute *authz = NULL; /* if not rootdn and dgAuthz is present, * check if user can be authorized as dgIdentity */ if ( ad_dgAuthz && !BER_BVISEMPTY( &id->a_nvals[0] ) && !be_isroot( op ) && ( authz = attrs_find( rs->sr_entry->e_attrs, ad_dgAuthz ) ) ) { if ( slap_sasl_matches( op, authz->a_nvals, &o.o_ndn, &o.o_ndn ) != LDAP_SUCCESS ) { return SLAP_CB_CONTINUE; } } o.o_dn = id->a_vals[0]; o.o_ndn = id->a_nvals[0]; o.o_groups = NULL; } e = rs->sr_entry; /* ensure e is modifiable, but do not replace * sr_entry yet since we have pointers into it */ if ( !( rs->sr_flags & REP_ENTRY_MODIFIABLE ) ) { e = entry_dup( rs->sr_entry ); } dlc.dlc_e = e; dlc.dlc_dli = dli; cb.sc_private = &dlc; cb.sc_response = dynlist_sc_update; o.o_callback = &cb; o.ors_deref = LDAP_DEREF_NEVER; o.ors_limit = NULL; o.ors_tlimit = SLAP_NO_LIMIT; o.ors_slimit = SLAP_NO_LIMIT; for ( url = a->a_nvals; !BER_BVISNULL( url ); url++ ) { LDAPURLDesc *lud = NULL; int i, j; struct berval dn; int rc; BER_BVZERO( &o.o_req_dn ); BER_BVZERO( &o.o_req_ndn ); o.ors_filter = NULL; o.ors_attrs = NULL; BER_BVZERO( &o.ors_filterstr ); if ( ldap_url_parse( url->bv_val, &lud ) != LDAP_URL_SUCCESS ) { /* FIXME: error? */ continue; } if ( lud->lud_host != NULL ) { /* FIXME: host not allowed; reject as illegal? */ Debug( LDAP_DEBUG_ANY, "dynlist_prepare_entry(\"%s\"): " "illegal URI \"%s\"\n", e->e_name.bv_val, url->bv_val, 0 ); goto cleanup; } if ( lud->lud_dn == NULL ) { /* note that an empty base is not honored in terms * of defaultSearchBase, because select_backend() * is not aware of the defaultSearchBase option; * this can be useful in case of a database serving * the empty suffix */ BER_BVSTR( &dn, "" ); } else { ber_str2bv( lud->lud_dn, 0, 0, &dn ); } rc = dnPrettyNormal( NULL, &dn, &o.o_req_dn, &o.o_req_ndn, op->o_tmpmemctx ); if ( rc != LDAP_SUCCESS ) { /* FIXME: error? */ goto cleanup; } o.ors_scope = lud->lud_scope; for ( dlm = dli->dli_dlm; dlm; dlm = dlm->dlm_next ) { if ( dlm->dlm_mapped_ad != NULL ) { break; } } if ( dli->dli_dlm && !dlm ) { /* if ( lud->lud_attrs != NULL ), * the URL should be ignored */ o.ors_attrs = slap_anlist_no_attrs; } else if ( lud->lud_attrs == NULL ) { o.ors_attrs = rs->sr_attrs; } else { for ( i = 0; lud->lud_attrs[i]; i++) /* just count */ ; o.ors_attrs = op->o_tmpcalloc( i + 1, sizeof( AttributeName ), op->o_tmpmemctx ); for ( i = 0, j = 0; lud->lud_attrs[i]; i++) { const char *text = NULL; ber_str2bv( lud->lud_attrs[i], 0, 0, &o.ors_attrs[j].an_name ); o.ors_attrs[j].an_desc = NULL; (void)slap_bv2ad( &o.ors_attrs[j].an_name, &o.ors_attrs[j].an_desc, &text ); /* FIXME: ignore errors... */ if ( rs->sr_attrs == NULL ) { if ( o.ors_attrs[j].an_desc != NULL && is_at_operational( o.ors_attrs[j].an_desc->ad_type ) ) { continue; } } else { if ( o.ors_attrs[j].an_desc != NULL && is_at_operational( o.ors_attrs[j].an_desc->ad_type ) ) { if ( !opattrs ) { continue; } if ( !ad_inlist( o.ors_attrs[j].an_desc, rs->sr_attrs ) ) { /* lookup if mapped -- linear search, * not very efficient unless list * is very short */ for ( dlm = dli->dli_dlm; dlm; dlm = dlm->dlm_next ) { if ( dlm->dlm_member_ad == o.ors_attrs[j].an_desc ) { break; } } if ( dlm == NULL ) { continue; } } } else { if ( !userattrs && o.ors_attrs[j].an_desc != NULL && !ad_inlist( o.ors_attrs[j].an_desc, rs->sr_attrs ) ) { /* lookup if mapped -- linear search, * not very efficient unless list * is very short */ for ( dlm = dli->dli_dlm; dlm; dlm = dlm->dlm_next ) { if ( dlm->dlm_member_ad == o.ors_attrs[j].an_desc ) { break; } } if ( dlm == NULL ) { continue; } } } } j++; } if ( j == 0 ) { goto cleanup; } BER_BVZERO( &o.ors_attrs[j].an_name ); } if ( lud->lud_filter == NULL ) { ber_dupbv_x( &o.ors_filterstr, &dli->dli_default_filter, op->o_tmpmemctx ); } else { struct berval flt; ber_str2bv( lud->lud_filter, 0, 0, &flt ); if ( dynlist_make_filter( op, rs->sr_entry, url->bv_val, &flt, &o.ors_filterstr ) ) { /* error */ goto cleanup; } } o.ors_filter = str2filter_x( op, o.ors_filterstr.bv_val ); if ( o.ors_filter == NULL ) { goto cleanup; } o.o_bd = select_backend( &o.o_req_ndn, 1 ); if ( o.o_bd && o.o_bd->be_search ) { SlapReply r = { REP_SEARCH }; r.sr_attr_flags = slap_attr_flags( o.ors_attrs ); (void)o.o_bd->be_search( &o, &r ); } cleanup:; if ( id ) { slap_op_groups_free( &o ); } if ( o.ors_filter ) { filter_free_x( &o, o.ors_filter, 1 ); } if ( o.ors_attrs && o.ors_attrs != rs->sr_attrs && o.ors_attrs != slap_anlist_no_attrs ) { op->o_tmpfree( o.ors_attrs, op->o_tmpmemctx ); } if ( !BER_BVISNULL( &o.o_req_dn ) ) { op->o_tmpfree( o.o_req_dn.bv_val, op->o_tmpmemctx ); } if ( !BER_BVISNULL( &o.o_req_ndn ) ) { op->o_tmpfree( o.o_req_ndn.bv_val, op->o_tmpmemctx ); } assert( BER_BVISNULL( &o.ors_filterstr ) || o.ors_filterstr.bv_val != lud->lud_filter ); op->o_tmpfree( o.ors_filterstr.bv_val, op->o_tmpmemctx ); ldap_free_urldesc( lud ); } if ( e != rs->sr_entry ) { rs_replace_entry( op, rs, (slap_overinst *)op->o_bd->bd_info, e ); rs->sr_flags |= REP_ENTRY_MODIFIABLE | REP_ENTRY_MUSTBEFREED; } return SLAP_CB_CONTINUE; }
int do_delete( Operation *op, SlapReply *rs ) { struct berval dn = BER_BVNULL; Debug( LDAP_DEBUG_TRACE, "%s do_delete\n", op->o_log_prefix, 0, 0 ); /* * Parse the delete request. It looks like this: * * DelRequest := DistinguishedName */ if ( ber_scanf( op->o_ber, "m", &dn ) == LBER_ERROR ) { Debug( LDAP_DEBUG_ANY, "%s do_delete: ber_scanf failed\n", op->o_log_prefix, 0, 0 ); send_ldap_discon( op, rs, LDAP_PROTOCOL_ERROR, "decoding error" ); return SLAPD_DISCONNECT; } if( get_ctrls( op, rs, 1 ) != LDAP_SUCCESS ) { Debug( LDAP_DEBUG_ANY, "%s do_delete: get_ctrls failed\n", op->o_log_prefix, 0, 0 ); goto cleanup; } rs->sr_err = dnPrettyNormal( NULL, &dn, &op->o_req_dn, &op->o_req_ndn, op->o_tmpmemctx ); if( rs->sr_err != LDAP_SUCCESS ) { Debug( LDAP_DEBUG_ANY, "%s do_delete: invalid dn (%s)\n", op->o_log_prefix, dn.bv_val, 0 ); send_ldap_error( op, rs, LDAP_INVALID_DN_SYNTAX, "invalid DN" ); goto cleanup; } Statslog( LDAP_DEBUG_STATS, "%s DEL dn=\"%s\"\n", op->o_log_prefix, op->o_req_dn.bv_val, 0, 0, 0 ); if( op->o_req_ndn.bv_len == 0 ) { Debug( LDAP_DEBUG_ANY, "%s do_delete: root dse!\n", op->o_log_prefix, 0, 0 ); /* protocolError would likely be a more appropriate error */ send_ldap_error( op, rs, LDAP_UNWILLING_TO_PERFORM, "cannot delete the root DSE" ); goto cleanup; } else if ( bvmatch( &op->o_req_ndn, &frontendDB->be_schemandn ) ) { Debug( LDAP_DEBUG_ANY, "%s do_delete: subschema subentry!\n", op->o_log_prefix, 0, 0 ); /* protocolError would likely be a more appropriate error */ send_ldap_error( op, rs, LDAP_UNWILLING_TO_PERFORM, "cannot delete the root DSE" ); goto cleanup; } op->o_bd = frontendDB; rs->sr_err = frontendDB->be_delete( op, rs ); #ifdef LDAP_X_TXN if( rs->sr_err == LDAP_X_TXN_SPECIFY_OKAY ) { /* skip cleanup */ return rs->sr_err; } #endif cleanup:; op->o_tmpfree( op->o_req_dn.bv_val, op->o_tmpmemctx ); op->o_tmpfree( op->o_req_ndn.bv_val, op->o_tmpmemctx ); return rs->sr_err; }
int do_modify( Operation *op, SlapReply *rs ) { struct berval dn = BER_BVNULL; char textbuf[ SLAP_TEXT_BUFLEN ]; size_t textlen = sizeof( textbuf ); #ifdef LDAP_DEBUG Modifications *tmp; #endif Debug( LDAP_DEBUG_TRACE, "%s do_modify\n", op->o_log_prefix, 0, 0 ); /* * Parse the modify request. It looks like this: * * ModifyRequest := [APPLICATION 6] SEQUENCE { * name DistinguishedName, * mods SEQUENCE OF SEQUENCE { * operation ENUMERATED { * add (0), * delete (1), * replace (2) * }, * modification SEQUENCE { * type AttributeType, * values SET OF AttributeValue * } * } * } */ if ( ber_scanf( op->o_ber, "{m" /*}*/, &dn ) == LBER_ERROR ) { Debug( LDAP_DEBUG_ANY, "%s do_modify: ber_scanf failed\n", op->o_log_prefix, 0, 0 ); send_ldap_discon( op, rs, LDAP_PROTOCOL_ERROR, "decoding error" ); return SLAPD_DISCONNECT; } Debug( LDAP_DEBUG_ARGS, "%s do_modify: dn (%s)\n", op->o_log_prefix, dn.bv_val, 0 ); rs->sr_err = slap_parse_modlist( op, rs, op->o_ber, &op->oq_modify ); if ( rs->sr_err != LDAP_SUCCESS ) { Debug( LDAP_DEBUG_ANY, "%s do_modify: slap_parse_modlist failed err=%d msg=%s\n", op->o_log_prefix, rs->sr_err, rs->sr_text ); send_ldap_result( op, rs ); goto cleanup; } if( get_ctrls( op, rs, 1 ) != LDAP_SUCCESS ) { Debug( LDAP_DEBUG_ANY, "%s do_modify: get_ctrls failed\n", op->o_log_prefix, 0, 0 ); /* get_ctrls has sent results. Now clean up. */ goto cleanup; } rs->sr_err = dnPrettyNormal( NULL, &dn, &op->o_req_dn, &op->o_req_ndn, op->o_tmpmemctx ); if( rs->sr_err != LDAP_SUCCESS ) { Debug( LDAP_DEBUG_ANY, "%s do_modify: invalid dn (%s)\n", op->o_log_prefix, dn.bv_val, 0 ); send_ldap_error( op, rs, LDAP_INVALID_DN_SYNTAX, "invalid DN" ); goto cleanup; } op->orm_no_opattrs = 0; #ifdef LDAP_DEBUG Debug( LDAP_DEBUG_ARGS, "%s modifications:\n", op->o_log_prefix, 0, 0 ); for ( tmp = op->orm_modlist; tmp != NULL; tmp = tmp->sml_next ) { Debug( LDAP_DEBUG_ARGS, "\t%s: %s\n", tmp->sml_op == LDAP_MOD_ADD ? "add" : (tmp->sml_op == LDAP_MOD_INCREMENT ? "increment" : (tmp->sml_op == LDAP_MOD_DELETE ? "delete" : "replace")), tmp->sml_type.bv_val, 0 ); if ( tmp->sml_values == NULL ) { Debug( LDAP_DEBUG_ARGS, "%s\n", "\t\tno values", NULL, NULL ); } else if ( BER_BVISNULL( &tmp->sml_values[ 0 ] ) ) { Debug( LDAP_DEBUG_ARGS, "%s\n", "\t\tzero values", NULL, NULL ); } else if ( BER_BVISNULL( &tmp->sml_values[ 1 ] ) ) { Debug( LDAP_DEBUG_ARGS, "%s, length %ld\n", "\t\tone value", (long) tmp->sml_values[0].bv_len, NULL ); } else { Debug( LDAP_DEBUG_ARGS, "%s\n", "\t\tmultiple values", NULL, NULL ); } } if ( StatslogTest( LDAP_DEBUG_STATS ) ) { char abuf[BUFSIZ/2], *ptr = abuf; int len = 0; Statslog( LDAP_DEBUG_STATS, "%s MOD dn=\"%s\"\n", op->o_log_prefix, op->o_req_dn.bv_val, 0, 0, 0 ); for ( tmp = op->orm_modlist; tmp != NULL; tmp = tmp->sml_next ) { if (len + 1 + tmp->sml_type.bv_len > sizeof(abuf)) { Statslog( LDAP_DEBUG_STATS, "%s MOD attr=%s\n", op->o_log_prefix, abuf, 0, 0, 0 ); len = 0; ptr = abuf; if( 1 + tmp->sml_type.bv_len > sizeof(abuf)) { Statslog( LDAP_DEBUG_STATS, "%s MOD attr=%s\n", op->o_log_prefix, tmp->sml_type.bv_val, 0, 0, 0 ); continue; } } if (len) { *ptr++ = ' '; len++; } ptr = lutil_strcopy(ptr, tmp->sml_type.bv_val); len += tmp->sml_type.bv_len; } if (len) { Statslog( LDAP_DEBUG_STATS, "%s MOD attr=%s\n", op->o_log_prefix, abuf, 0, 0, 0 ); } } #endif /* LDAP_DEBUG */ rs->sr_err = slap_mods_check( op, op->orm_modlist, &rs->sr_text, textbuf, textlen, NULL ); if ( rs->sr_err != LDAP_SUCCESS ) { send_ldap_result( op, rs ); goto cleanup; } op->o_bd = frontendDB; rs->sr_err = frontendDB->be_modify( op, rs ); #ifdef LDAP_X_TXN if( rs->sr_err == LDAP_X_TXN_SPECIFY_OKAY ) { /* skip cleanup */ return rs->sr_err; } #endif cleanup: op->o_tmpfree( op->o_req_dn.bv_val, op->o_tmpmemctx ); op->o_tmpfree( op->o_req_ndn.bv_val, op->o_tmpmemctx ); if ( op->orm_modlist != NULL ) slap_mods_free( op->orm_modlist, 1 ); return rs->sr_err; }
int do_search( Operation *op, /* info about the op to which we're responding */ SlapReply *rs /* all the response data we'll send */ ) { struct berval base = BER_BVNULL; ber_len_t siz, off, i; Debug( LDAP_DEBUG_TRACE, "%s do_search\n", op->o_log_prefix, 0, 0 ); /* * Parse the search request. It looks like this: * * SearchRequest := [APPLICATION 3] SEQUENCE { * baseObject DistinguishedName, * scope ENUMERATED { * baseObject (0), * singleLevel (1), * wholeSubtree (2), * subordinate (3) -- OpenLDAP extension * }, * derefAliases ENUMERATED { * neverDerefaliases (0), * derefInSearching (1), * derefFindingBaseObj (2), * alwaysDerefAliases (3) * }, * sizelimit INTEGER (0 .. 65535), * timelimit INTEGER (0 .. 65535), * attrsOnly BOOLEAN, * filter Filter, * attributes SEQUENCE OF AttributeType * } */ /* baseObject, scope, derefAliases, sizelimit, timelimit, attrsOnly */ if ( ber_scanf( op->o_ber, "{miiiib" /*}*/, &base, &op->ors_scope, &op->ors_deref, &op->ors_slimit, &op->ors_tlimit, &op->ors_attrsonly ) == LBER_ERROR ) { send_ldap_discon( op, rs, LDAP_PROTOCOL_ERROR, "decoding error" ); rs->sr_err = SLAPD_DISCONNECT; goto return_results; } if ( op->ors_tlimit < 0 || op->ors_tlimit > SLAP_MAX_LIMIT ) { send_ldap_error( op, rs, LDAP_PROTOCOL_ERROR, "invalid time limit" ); goto return_results; } if ( op->ors_slimit < 0 || op->ors_slimit > SLAP_MAX_LIMIT ) { send_ldap_error( op, rs, LDAP_PROTOCOL_ERROR, "invalid size limit" ); goto return_results; } switch( op->ors_scope ) { case LDAP_SCOPE_BASE: case LDAP_SCOPE_ONELEVEL: case LDAP_SCOPE_SUBTREE: case LDAP_SCOPE_SUBORDINATE: break; default: send_ldap_error( op, rs, LDAP_PROTOCOL_ERROR, "invalid scope" ); goto return_results; } switch( op->ors_deref ) { case LDAP_DEREF_NEVER: case LDAP_DEREF_FINDING: case LDAP_DEREF_SEARCHING: case LDAP_DEREF_ALWAYS: break; default: send_ldap_error( op, rs, LDAP_PROTOCOL_ERROR, "invalid deref" ); goto return_results; } rs->sr_err = dnPrettyNormal( NULL, &base, &op->o_req_dn, &op->o_req_ndn, op->o_tmpmemctx ); if( rs->sr_err != LDAP_SUCCESS ) { Debug( LDAP_DEBUG_ANY, "%s do_search: invalid dn: \"%s\"\n", op->o_log_prefix, base.bv_val, 0 ); send_ldap_error( op, rs, LDAP_INVALID_DN_SYNTAX, "invalid DN" ); goto return_results; } Debug( LDAP_DEBUG_ARGS, "SRCH \"%s\" %d %d", base.bv_val, op->ors_scope, op->ors_deref ); Debug( LDAP_DEBUG_ARGS, " %d %d %d\n", op->ors_slimit, op->ors_tlimit, op->ors_attrsonly); /* filter - returns a "normalized" version */ rs->sr_err = get_filter( op, op->o_ber, &op->ors_filter, &rs->sr_text ); if( rs->sr_err != LDAP_SUCCESS ) { if( rs->sr_err == SLAPD_DISCONNECT ) { rs->sr_err = LDAP_PROTOCOL_ERROR; send_ldap_disconnect( op, rs ); rs->sr_err = SLAPD_DISCONNECT; } else { send_ldap_result( op, rs ); } goto return_results; } filter2bv_x( op, op->ors_filter, &op->ors_filterstr ); Debug( LDAP_DEBUG_ARGS, " filter: %s\n", !BER_BVISEMPTY( &op->ors_filterstr ) ? op->ors_filterstr.bv_val : "empty", 0, 0 ); /* attributes */ siz = sizeof(AttributeName); off = offsetof(AttributeName,an_name); if ( ber_scanf( op->o_ber, "{M}}", &op->ors_attrs, &siz, off ) == LBER_ERROR ) { send_ldap_discon( op, rs, LDAP_PROTOCOL_ERROR, "decoding attrs error" ); rs->sr_err = SLAPD_DISCONNECT; goto return_results; } for ( i=0; i<siz; i++ ) { const char *dummy; /* ignore msgs from bv2ad */ op->ors_attrs[i].an_desc = NULL; op->ors_attrs[i].an_oc = NULL; op->ors_attrs[i].an_flags = 0; if ( slap_bv2ad( &op->ors_attrs[i].an_name, &op->ors_attrs[i].an_desc, &dummy ) != LDAP_SUCCESS ) { if ( slap_bv2undef_ad( &op->ors_attrs[i].an_name, &op->ors_attrs[i].an_desc, &dummy, SLAP_AD_PROXIED|SLAP_AD_NOINSERT ) ) { struct berval *bv = &op->ors_attrs[i].an_name; /* RFC 4511 LDAPv3: All User Attributes */ if ( bvmatch( bv, slap_bv_all_user_attrs ) ) { continue; } /* RFC 3673 LDAPv3: All Operational Attributes */ if ( bvmatch( bv, slap_bv_all_operational_attrs ) ) { continue; } /* RFC 4529 LDAP: Requesting Attributes by Object Class */ if ( bv->bv_len > 1 && bv->bv_val[0] == '@' ) { /* FIXME: check if remaining is valid oc name? */ continue; } /* add more "exceptions" to RFC 4511 4.5.1.8. */ /* invalid attribute description? remove */ if ( ad_keystring( bv ) ) { /* NOTE: parsed in-place, don't modify; * rather add "1.1", which must be ignored */ BER_BVSTR( &op->ors_attrs[i].an_name, LDAP_NO_ATTRS ); } /* otherwise leave in place... */ } } } if( get_ctrls( op, rs, 1 ) != LDAP_SUCCESS ) { Debug( LDAP_DEBUG_ANY, "%s do_search: get_ctrls failed\n", op->o_log_prefix, 0, 0 ); goto return_results; } Debug( LDAP_DEBUG_ARGS, " attrs:", 0, 0, 0 ); if ( siz != 0 ) { for ( i = 0; i<siz; i++ ) { Debug( LDAP_DEBUG_ARGS, " %s", op->ors_attrs[i].an_name.bv_val, 0, 0 ); } } Debug( LDAP_DEBUG_ARGS, "\n", 0, 0, 0 ); if ( StatslogTest( LDAP_DEBUG_STATS ) ) { char abuf[BUFSIZ/2], *ptr = abuf; unsigned len = 0, alen; sprintf(abuf, "scope=%d deref=%d", op->ors_scope, op->ors_deref); Statslog( LDAP_DEBUG_STATS, "%s SRCH base=\"%s\" %s filter=\"%s\"\n", op->o_log_prefix, op->o_req_dn.bv_val, abuf, op->ors_filterstr.bv_val, 0 ); for ( i = 0; i<siz; i++ ) { alen = op->ors_attrs[i].an_name.bv_len; if (alen >= sizeof(abuf)) { alen = sizeof(abuf)-1; } if (len && (len + 1 + alen >= sizeof(abuf))) { Statslog( LDAP_DEBUG_STATS, "%s SRCH attr=%s\n", op->o_log_prefix, abuf, 0, 0, 0 ); len = 0; ptr = abuf; } if (len) { *ptr++ = ' '; len++; } ptr = lutil_strncopy(ptr, op->ors_attrs[i].an_name.bv_val, alen); len += alen; *ptr = '\0'; } if (len) { Statslog( LDAP_DEBUG_STATS, "%s SRCH attr=%s\n", op->o_log_prefix, abuf, 0, 0, 0 ); } } op->o_bd = frontendDB; rs->sr_err = frontendDB->be_search( op, rs ); return_results:; if ( !BER_BVISNULL( &op->o_req_dn ) ) { slap_sl_free( op->o_req_dn.bv_val, op->o_tmpmemctx ); } if ( !BER_BVISNULL( &op->o_req_ndn ) ) { slap_sl_free( op->o_req_ndn.bv_val, op->o_tmpmemctx ); } if ( !BER_BVISNULL( &op->ors_filterstr ) ) { op->o_tmpfree( op->ors_filterstr.bv_val, op->o_tmpmemctx ); } if ( op->ors_filter != NULL) { filter_free_x( op, op->ors_filter, 1 ); } if ( op->ors_attrs != NULL ) { op->o_tmpfree( op->ors_attrs, op->o_tmpmemctx ); } return rs->sr_err; }
int slapdn( int argc, char **argv ) { int rc = 0; const char *progname = "slapdn"; slap_tool_init( progname, SLAPDN, argc, argv ); argv = &argv[ optind ]; argc -= optind; for ( ; argc--; argv++ ) { struct berval dn, pdn = BER_BVNULL, ndn = BER_BVNULL; ber_str2bv( argv[ 0 ], 0, 0, &dn ); switch ( dn_mode ) { case SLAP_TOOL_LDAPDN_PRETTY: rc = dnPretty( NULL, &dn, &pdn, NULL ); break; case SLAP_TOOL_LDAPDN_NORMAL: rc = dnNormalize( 0, NULL, NULL, &dn, &ndn, NULL ); break; default: rc = dnPrettyNormal( NULL, &dn, &pdn, &ndn, NULL ); break; } if ( rc != LDAP_SUCCESS ) { fprintf( stderr, "DN: <%s> check failed %d (%s)\n", dn.bv_val, rc, ldap_err2string( rc ) ); if ( !continuemode ) { rc = -1; break; } } else { switch ( dn_mode ) { case SLAP_TOOL_LDAPDN_PRETTY: printf( "%s\n", pdn.bv_val ); break; case SLAP_TOOL_LDAPDN_NORMAL: printf( "%s\n", ndn.bv_val ); break; default: printf( "DN: <%s> check succeeded\n" "normalized: <%s>\n" "pretty: <%s>\n", dn.bv_val, ndn.bv_val, pdn.bv_val ); break; } ch_free( ndn.bv_val ); ch_free( pdn.bv_val ); } } if ( slap_tool_destroy()) rc = EXIT_FAILURE; return rc; }