Пример #1
0
/* Check that all filter terms reside in the same table.
 *
 * If any of the filter terms are indexed, then only an IndexScan of the OL_index
 * will be performed. If none are indexed, but all the terms reside in a single
 * table, a Scan can be performed with the LDAP filter transformed into a ScanFilter.
 *
 * Otherwise, a full scan of the DB must be done with all filtering done by slapd.
 */
static int ndb_filter_check( struct ndb_info *ni, Filter *f,
	NdbOcInfo **oci, int *indexed, int *ocfilter )
{
	AttributeDescription *ad = NULL;
	ber_tag_t choice = f->f_choice;
	int rc = 0, undef = 0;

	if ( choice & SLAPD_FILTER_UNDEFINED ) {
		choice &= SLAPD_FILTER_MASK;
		undef = 1;
	}
	switch( choice ) {
	case LDAP_FILTER_AND:
	case LDAP_FILTER_OR:
	case LDAP_FILTER_NOT:
		for ( f = f->f_list; f; f=f->f_next ) {
			rc = ndb_filter_check( ni, f, oci, indexed, ocfilter );
			if ( rc ) return rc;
		}
		break;
	case LDAP_FILTER_PRESENT:
		ad = f->f_desc;
		break;
	case LDAP_FILTER_EQUALITY:
	case LDAP_FILTER_SUBSTRINGS:
	case LDAP_FILTER_GE:
	case LDAP_FILTER_LE:
	case LDAP_FILTER_APPROX:
		ad = f->f_av_desc;
		break;
	default:
		break;
	}
	if ( ad && !undef ) {
		NdbAttrInfo *ai;
		/* ObjectClass filtering is in dn2id table */
		if ( ad == slap_schema.si_ad_objectClass ) {
			if ( choice == LDAP_FILTER_EQUALITY )
				(*ocfilter)++;
			return 0;
		}
		ai = ndb_ai_find( ni, ad->ad_type );
		if ( ai ) {
			if ( ai->na_flag & NDB_INFO_INDEX )
				(*indexed)++;
			if ( *oci ) {
				if ( ai->na_oi != *oci )
					rc = -1;
			} else {
				*oci = ai->na_oi;
			}
		}
	}
	return rc;
}
Пример #2
0
int ndb_modify_internal(
	Operation *op,
	NdbArgs *NA,
	const char **text,
	char *textbuf,
	size_t textlen )
{
	struct ndb_info *ni = (struct ndb_info *) op->o_bd->be_private;
	Modification	*mod;
	Modifications	*ml;
	Modifications	*modlist = op->orm_modlist;
	NdbAttrInfo **modai, *atmp;
	const NdbDictionary::Dictionary *myDict;
	const NdbDictionary::Table *myTable;
	int got_oc = 0, nmods = 0, nai = 0, i, j;
	int rc, indexed = 0;
	Attribute *old = NULL;

	Debug( LDAP_DEBUG_TRACE, "ndb_modify_internal: 0x%08lx: %s\n",
		NA->e->e_id, NA->e->e_dn, 0);

	if ( !acl_check_modlist( op, NA->e, modlist )) {
		return LDAP_INSUFFICIENT_ACCESS;
	}

	old = attrs_dup( NA->e->e_attrs );

	for ( ml = modlist; ml != NULL; ml = ml->sml_next ) {
		mod = &ml->sml_mod;
		nmods++;

		switch ( mod->sm_op ) {
		case LDAP_MOD_ADD:
			Debug(LDAP_DEBUG_ARGS,
				"ndb_modify_internal: add %s\n",
				mod->sm_desc->ad_cname.bv_val, 0, 0);
			rc = modify_add_values( NA->e, mod, get_permissiveModify(op),
				text, textbuf, textlen );
			if( rc != LDAP_SUCCESS ) {
				Debug(LDAP_DEBUG_ARGS, "ndb_modify_internal: %d %s\n",
					rc, *text, 0);
			}
			break;

		case LDAP_MOD_DELETE:
			Debug(LDAP_DEBUG_ARGS,
				"ndb_modify_internal: delete %s\n",
				mod->sm_desc->ad_cname.bv_val, 0, 0);
			rc = ndb_modify_delete( NA->e, mod, get_permissiveModify(op),
				text, textbuf, textlen, NULL );
			assert( rc != LDAP_TYPE_OR_VALUE_EXISTS );
			if( rc != LDAP_SUCCESS ) {
				Debug(LDAP_DEBUG_ARGS, "ndb_modify_internal: %d %s\n",
					rc, *text, 0);
			}
			break;

		case LDAP_MOD_REPLACE:
			Debug(LDAP_DEBUG_ARGS,
				"ndb_modify_internal: replace %s\n",
				mod->sm_desc->ad_cname.bv_val, 0, 0);
			rc = modify_replace_values( NA->e, mod, get_permissiveModify(op),
				text, textbuf, textlen );
			if( rc != LDAP_SUCCESS ) {
				Debug(LDAP_DEBUG_ARGS, "ndb_modify_internal: %d %s\n",
					rc, *text, 0);
			}
			break;

		case LDAP_MOD_INCREMENT:
			Debug(LDAP_DEBUG_ARGS,
				"ndb_modify_internal: increment %s\n",
				mod->sm_desc->ad_cname.bv_val, 0, 0);
			rc = modify_increment_values( NA->e, mod, get_permissiveModify(op),
				text, textbuf, textlen );
			if( rc != LDAP_SUCCESS ) {
				Debug(LDAP_DEBUG_ARGS,
					"ndb_modify_internal: %d %s\n",
					rc, *text, 0);
			}
			break;

		case SLAP_MOD_SOFTADD:
			Debug(LDAP_DEBUG_ARGS,
				"ndb_modify_internal: softadd %s\n",
				mod->sm_desc->ad_cname.bv_val, 0, 0);
 			mod->sm_op = LDAP_MOD_ADD;

			rc = modify_add_values( NA->e, mod, get_permissiveModify(op),
				text, textbuf, textlen );

 			mod->sm_op = SLAP_MOD_SOFTADD;

 			if ( rc == LDAP_TYPE_OR_VALUE_EXISTS ) {
 				rc = LDAP_SUCCESS;
 			}

			if( rc != LDAP_SUCCESS ) {
				Debug(LDAP_DEBUG_ARGS, "ndb_modify_internal: %d %s\n",
					rc, *text, 0);
			}
 			break;

		case SLAP_MOD_SOFTDEL:
			Debug(LDAP_DEBUG_ARGS,
				"ndb_modify_internal: softdel %s\n",
				mod->sm_desc->ad_cname.bv_val, 0, 0);
 			mod->sm_op = LDAP_MOD_DELETE;

			rc = modify_delete_values( NA->e, mod, get_permissiveModify(op),
				text, textbuf, textlen );

 			mod->sm_op = SLAP_MOD_SOFTDEL;

 			if ( rc == LDAP_NO_SUCH_ATTRIBUTE) {
 				rc = LDAP_SUCCESS;
 			}

			if( rc != LDAP_SUCCESS ) {
				Debug(LDAP_DEBUG_ARGS, "ndb_modify_internal: %d %s\n",
					rc, *text, 0);
			}
 			break;

		case SLAP_MOD_ADD_IF_NOT_PRESENT:
			Debug(LDAP_DEBUG_ARGS,
				"ndb_modify_internal: add_if_not_present %s\n",
				mod->sm_desc->ad_cname.bv_val, 0, 0);
			if ( attr_find( NA->e->e_attrs, mod->sm_desc ) ) {
				rc = LDAP_SUCCESS;
				break;
			}

 			mod->sm_op = LDAP_MOD_ADD;

			rc = modify_add_values( NA->e, mod, get_permissiveModify(op),
				text, textbuf, textlen );

 			mod->sm_op = SLAP_MOD_ADD_IF_NOT_PRESENT;

			if( rc != LDAP_SUCCESS ) {
				Debug(LDAP_DEBUG_ARGS, "ndb_modify_internal: %d %s\n",
					rc, *text, 0);
			}
 			break;

		default:
			Debug(LDAP_DEBUG_ANY, "ndb_modify_internal: invalid op %d\n",
				mod->sm_op, 0, 0);
			*text = "Invalid modify operation";
			rc = LDAP_OTHER;
			Debug(LDAP_DEBUG_ARGS, "ndb_modify_internal: %d %s\n",
				rc, *text, 0);
		}

		if ( rc != LDAP_SUCCESS ) {
			attrs_free( old );
			return rc; 
		}

		/* If objectClass was modified, reset the flags */
		if ( mod->sm_desc == slap_schema.si_ad_objectClass ) {
			NA->e->e_ocflags = 0;
			got_oc = 1;
		}
	}

	/* check that the entry still obeys the schema */
	rc = entry_schema_check( op, NA->e, NULL, get_relax(op), 0, NULL,
		text, textbuf, textlen );
	if ( rc != LDAP_SUCCESS || op->o_noop ) {
		if ( rc != LDAP_SUCCESS ) {
			Debug( LDAP_DEBUG_ANY,
				"entry failed schema check: %s\n",
				*text, 0, 0 );
		}
		attrs_free( old );
		return rc;
	}

	if ( got_oc ) {
		rc = ndb_entry_put_info( op->o_bd, NA, 1 );
		if ( rc ) {
			attrs_free( old );
			return rc;
		}
	}

	/* apply modifications to DB */
	modai = (NdbAttrInfo **)op->o_tmpalloc( nmods * sizeof(NdbAttrInfo*), op->o_tmpmemctx );

	/* Get the unique list of modified attributes */
	ldap_pvt_thread_rdwr_rlock( &ni->ni_ai_rwlock );
	for ( ml = modlist; ml != NULL; ml = ml->sml_next ) {
		/* Already took care of objectclass */
		if ( ml->sml_desc == slap_schema.si_ad_objectClass )
			continue;
		for ( i=0; i<nai; i++ ) {
			if ( ml->sml_desc->ad_type == modai[i]->na_attr )
				break;
		}
		/* This attr was already updated */
		if ( i < nai )
			continue;
		modai[nai] = ndb_ai_find( ni, ml->sml_desc->ad_type );
		if ( modai[nai]->na_flag & NDB_INFO_INDEX )
			indexed++;
		nai++;
	}
	ldap_pvt_thread_rdwr_runlock( &ni->ni_ai_rwlock );

	/* If got_oc, this was already done above */
	if ( indexed && !got_oc) {
		rc = ndb_entry_put_info( op->o_bd, NA, 1 );
		if ( rc ) {
			attrs_free( old );
			return rc;
		}
	}

	myDict = NA->ndb->getDictionary();

	/* sort modai so that OcInfo's are contiguous */
	{
		int j, k;
		for ( i=0; i<nai; i++ ) {
			for ( j=i+1; j<nai; j++ ) {
				if ( modai[i]->na_oi == modai[j]->na_oi )
					continue;
				for ( k=j+1; k<nai; k++ ) {
					if ( modai[i]->na_oi == modai[k]->na_oi ) {
						atmp = modai[j];
						modai[j] = modai[k];
						modai[k] = atmp;
						break;
					}
				}
				/* there are no more na_oi's that match modai[i] */
				if ( k == nai ) {
					i = j;
				}
			}
		}
	}

	/* One call per table... */
	for ( i=0; i<nai; i += j ) {
		atmp = modai[i];
		for ( j=i+1; j<nai; j++ )
			if ( atmp->na_oi != modai[j]->na_oi )
				break;
		j -= i;
		myTable = myDict->getTable( atmp->na_oi->no_table.bv_val );
		if ( !myTable )
			continue;
		rc = ndb_oc_attrs( NA->txn, myTable, NA->e, atmp->na_oi, &modai[i], j, old );
		if ( rc ) break;
	}
	attrs_free( old );
	return rc;
}
Пример #3
0
static int ndb_filter_set( Operation *op, struct ndb_info *ni, Filter *f, int indexed,
	NdbIndexScanOperation *scan, NdbScanFilter *sf, int *bounds )
{
	AttributeDescription *ad = NULL;
	ber_tag_t choice = f->f_choice;
	int undef = 0;

	if ( choice & SLAPD_FILTER_UNDEFINED ) {
		choice &= SLAPD_FILTER_MASK;
		undef = 1;
	}
	switch( choice ) {
	case LDAP_FILTER_NOT:
		/* no indexing for these */
		break;
	case LDAP_FILTER_OR:
		/* FIXME: these bounds aren't right. */
		if ( indexed ) {
			scan->end_of_bound( (*bounds)++ );
		}
	case LDAP_FILTER_AND:
		if ( sf ) {
			sf->begin( choice == LDAP_FILTER_OR ? NdbScanFilter::OR : NdbScanFilter::AND );
		}
		for ( f = f->f_list; f; f=f->f_next ) {
			if ( ndb_filter_set( op, ni, f, indexed, scan, sf, bounds ))
				return -1;
		}
		if ( sf ) {
			sf->end();
		}
		break;
	case LDAP_FILTER_PRESENT:
		ad = f->f_desc;
		break;
	case LDAP_FILTER_EQUALITY:
	case LDAP_FILTER_SUBSTRINGS:
	case LDAP_FILTER_GE:
	case LDAP_FILTER_LE:
	case LDAP_FILTER_APPROX:
		ad = f->f_av_desc;
		break;
	default:
		break;
	}
	if ( ad && !undef ) {
		NdbAttrInfo *ai;
		/* ObjectClass filtering is in dn2id table */
		if ( ad == slap_schema.si_ad_objectClass ) {
			return 0;
		}
		ai = ndb_ai_find( ni, ad->ad_type );
		if ( ai ) {
			int rc;
			if ( ai->na_flag & NDB_INFO_INDEX ) {
				char *buf, *ptr;
				NdbIndexScanOperation::BoundType bt;

				switch(choice) {
				case LDAP_FILTER_PRESENT:
					rc = scan->setBound( ai->na_ixcol - IDX_COLUMN,
						NdbIndexScanOperation::BoundGT, NULL );
					break;
				case LDAP_FILTER_EQUALITY:
				case LDAP_FILTER_APPROX:
					bt = NdbIndexScanOperation::BoundEQ;
					goto setit;
				case LDAP_FILTER_GE:
					bt = NdbIndexScanOperation::BoundGE;
					goto setit;
				case LDAP_FILTER_LE:
					bt = NdbIndexScanOperation::BoundLE;
				setit:
					rc = f->f_av_value.bv_len+1;
					if ( ai->na_len > 255 )
						rc++;
					buf = (char *)op->o_tmpalloc( rc, op->o_tmpmemctx );
					rc = f->f_av_value.bv_len;
					buf[0] = rc & 0xff;
					ptr = buf+1;
					if ( ai->na_len > 255 ) {
						buf[1] = (rc >> 8);
						ptr++;
					}
					memcpy( ptr, f->f_av_value.bv_val, f->f_av_value.bv_len );
					rc = scan->setBound( ai->na_ixcol - IDX_COLUMN, bt, buf );
					op->o_tmpfree( buf, op->o_tmpmemctx );
					break;
				default:
					break;
				}
			} else if ( sf ) {