Exemple #1
0
/*
 * massages "in" and normalizes it into "ndn"
 *
 * "ndn" may be untouched if no massaging occurred and its value was not null
 */
int
rwm_dn_massage_normalize(
	dncookie *dc,
	struct berval *in,
	struct berval *ndn )
{
	int		rc;
	struct berval	mdn = BER_BVNULL;
	
	/* massage 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( ndn ) ) {
		return rc;
	}

	rc = dnNormalize( 0, NULL, NULL, &mdn, ndn, NULL );

	if ( mdn.bv_val != in->bv_val ) {
		ch_free( mdn.bv_val );
	}

	return rc;
}
Exemple #2
0
const char *slapi_sdn_get_ndn( const Slapi_DN *sdn )
{
	if ( BER_BVISNULL( &sdn->ndn ) ) {
		dnNormalize( 0, NULL, NULL,
			(struct berval *)&sdn->dn, (struct berval *)&sdn->ndn, NULL );
		((Slapi_DN *)sdn)->flag |= FLAG_NDN;
	}

	return sdn->ndn.bv_val;
}
Exemple #3
0
Entry* ndb_tool_entry_get( BackendDB *be, ID id )
{
	NdbArgs NA;
	int rc;
	char text[1024];
	Operation op = {0};
	Opheader ohdr = {0};

	assert( be != NULL );
	assert( slapMode & SLAP_TOOL_MODE );

	NA.txn = myNdb->startTransaction();
	if ( !NA.txn ) {
		snprintf( text, sizeof(text),
			"start_transaction failed: %s (%d)",
			myNdb->getNdbError().message, myNdb->getNdbError().code );
		Debug( LDAP_DEBUG_ANY,
			"=> " LDAP_XSTRING(ndb_tool_entry_get) ": %s\n",
			 text, 0, 0 );
		return NULL;
	}

	NA.e = entry_alloc();
	NA.e->e_id = id;
	ber_dupbv( &NA.e->e_name, &myDn );
	dnNormalize( 0, NULL, NULL, &NA.e->e_name, &NA.e->e_nname, NULL );

	op.o_hdr = &ohdr;
	op.o_bd = be;
	op.o_tmpmemctx = NULL;
	op.o_tmpmfuncs = &ch_mfuncs;

	NA.ndb = myNdb;
	NA.ocs = myOcList;
	rc = ndb_entry_get_data( &op, &NA, 0 );

	if ( rc ) {
		entry_free( NA.e );
		NA.e = NULL;
	}
	NA.txn->close();

	return NA.e;
}
Exemple #4
0
static int pam_uid2dn(nssov_info *ni, Operation *op,
	struct paminfo *pi)
{
	struct berval sdn;

	BER_BVZERO(&pi->dn);

	if (!isvalidusername(&pi->uid)) {
		Debug(LDAP_DEBUG_ANY,"nssov_pam_uid2dn(%s): invalid user name\n",
			pi->uid.bv_val,0,0);
		return NSLCD_PAM_USER_UNKNOWN;
	}

	if (ni->ni_pam_opts & NI_PAM_SASL2DN) {
		int hlen = global_host_bv.bv_len;

		/* cn=<service>+uid=<user>,cn=<host>,cn=pam,cn=auth */
		sdn.bv_len = pi->uid.bv_len + pi->svc.bv_len + hlen +
			STRLENOF( "cn=+uid=,cn=,cn=pam,cn=auth" );
		sdn.bv_val = op->o_tmpalloc( sdn.bv_len + 1, op->o_tmpmemctx );
		sprintf(sdn.bv_val, "cn=%s+uid=%s,cn=%s,cn=pam,cn=auth",
			pi->svc.bv_val, pi->uid.bv_val, global_host_bv.bv_val);
		slap_sasl2dn(op, &sdn, &pi->dn, 0);
		op->o_tmpfree( sdn.bv_val, op->o_tmpmemctx );
	}

	/* If no luck, do a basic uid search */
	if (BER_BVISEMPTY(&pi->dn) && (ni->ni_pam_opts & NI_PAM_UID2DN)) {
		nssov_uid2dn(op, ni, &pi->uid, &pi->dn);
		if (!BER_BVISEMPTY(&pi->dn)) {
			sdn = pi->dn;
			dnNormalize( 0, NULL, NULL, &sdn, &pi->dn, op->o_tmpmemctx );
		}
	}
	if (BER_BVISEMPTY(&pi->dn)) {
		return NSLCD_PAM_USER_UNKNOWN;
	}
	return 0;
}
int
bdb_modrdn( Operation	*op, SlapReply *rs )
{
	struct bdb_info *bdb = (struct bdb_info *) op->o_bd->be_private;
	AttributeDescription *children = slap_schema.si_ad_children;
	AttributeDescription *entry = slap_schema.si_ad_entry;
	struct berval	p_dn, p_ndn;
	struct berval	new_dn = {0, NULL}, new_ndn = {0, NULL};
	Entry		*e = NULL;
	Entry		*p = NULL;
	EntryInfo	*ei = NULL, *eip = NULL, *nei = NULL, *neip = NULL;
	/* LDAP v2 supporting correct attribute handling. */
	char textbuf[SLAP_TEXT_BUFLEN];
	size_t textlen = sizeof textbuf;
	DB_TXN		*ltid = NULL, *lt2;
	struct bdb_op_info opinfo = {{{ 0 }}};
	Entry dummy = {0};

	Entry		*np = NULL;			/* newSuperior Entry */
	struct berval	*np_dn = NULL;			/* newSuperior dn */
	struct berval	*np_ndn = NULL;			/* newSuperior ndn */
	struct berval	*new_parent_dn = NULL;	/* np_dn, p_dn, or NULL */

	int		manageDSAit = get_manageDSAit( op );

	DB_LOCK		lock, plock, nplock;

	int		num_retries = 0;

	LDAPControl **preread_ctrl = NULL;
	LDAPControl **postread_ctrl = NULL;
	LDAPControl *ctrls[SLAP_MAX_RESPONSE_CONTROLS];
	int num_ctrls = 0;

	int	rc;

	int parent_is_glue = 0;
	int parent_is_leaf = 0;

#ifdef LDAP_X_TXN
	int settle = 0;
#endif

	Debug( LDAP_DEBUG_TRACE, "==>" LDAP_XSTRING(bdb_modrdn) "(%s,%s,%s)\n",
		op->o_req_dn.bv_val,op->oq_modrdn.rs_newrdn.bv_val,
		op->oq_modrdn.rs_newSup ? op->oq_modrdn.rs_newSup->bv_val : "NULL" );

#ifdef LDAP_X_TXN
	if( op->o_txnSpec ) {
		/* acquire connection lock */
		ldap_pvt_thread_mutex_lock( &op->o_conn->c_mutex );
		if( op->o_conn->c_txn == CONN_TXN_INACTIVE ) {
			rs->sr_text = "invalid transaction identifier";
			rs->sr_err = LDAP_X_TXN_ID_INVALID;
			goto txnReturn;
		} else if( op->o_conn->c_txn == CONN_TXN_SETTLE ) {
			settle=1;
			goto txnReturn;
		}

		if( op->o_conn->c_txn_backend == NULL ) {
			op->o_conn->c_txn_backend = op->o_bd;

		} else if( op->o_conn->c_txn_backend != op->o_bd ) {
			rs->sr_text = "transaction cannot span multiple database contexts";
			rs->sr_err = LDAP_AFFECTS_MULTIPLE_DSAS;
			goto txnReturn;
		}

		/* insert operation into transaction */

		rs->sr_text = "transaction specified";
		rs->sr_err = LDAP_X_TXN_SPECIFY_OKAY;

txnReturn:
		/* release connection lock */
		ldap_pvt_thread_mutex_unlock( &op->o_conn->c_mutex );

		if( !settle ) {
			send_ldap_result( op, rs );
			return rs->sr_err;
		}
	}
#endif

	ctrls[num_ctrls] = NULL;

	slap_mods_opattrs( op, &op->orr_modlist, 1 );

	if( 0 ) {
retry:	/* transaction retry */
		if ( dummy.e_attrs ) {
			attrs_free( dummy.e_attrs );
			dummy.e_attrs = NULL;
		}
		if (e != NULL) {
			bdb_unlocked_cache_return_entry_w(&bdb->bi_cache, e);
			e = NULL;
		}
		if (p != NULL) {
			bdb_unlocked_cache_return_entry_r(&bdb->bi_cache, p);
			p = NULL;
		}
		if (np != NULL) {
			bdb_unlocked_cache_return_entry_r(&bdb->bi_cache, np);
			np = NULL;
		}
		Debug( LDAP_DEBUG_TRACE, "==>" LDAP_XSTRING(bdb_modrdn)
				": retrying...\n", 0, 0, 0 );

		rs->sr_err = TXN_ABORT( ltid );
		ltid = NULL;
		LDAP_SLIST_REMOVE( &op->o_extra, &opinfo.boi_oe, OpExtra, oe_next );
		opinfo.boi_oe.oe_key = NULL;
		op->o_do_not_cache = opinfo.boi_acl_cache;
		if( rs->sr_err != 0 ) {
			rs->sr_err = LDAP_OTHER;
			rs->sr_text = "internal error";
			goto return_results;
		}
		if ( op->o_abandon ) {
			rs->sr_err = SLAPD_ABANDON;
			goto return_results;
		}
		parent_is_glue = 0;
		parent_is_leaf = 0;
		bdb_trans_backoff( ++num_retries );
	}

	/* begin transaction */
	rs->sr_err = TXN_BEGIN( bdb->bi_dbenv, NULL, &ltid, 
		bdb->bi_db_opflags );
	rs->sr_text = NULL;
	if( rs->sr_err != 0 ) {
		Debug( LDAP_DEBUG_TRACE,
			LDAP_XSTRING(bdb_modrdn) ": txn_begin failed: "
			"%s (%d)\n", db_strerror(rs->sr_err), rs->sr_err, 0 );
		rs->sr_err = LDAP_OTHER;
		rs->sr_text = "internal error";
		goto return_results;
	}
	Debug( LDAP_DEBUG_TRACE, LDAP_XSTRING(bdb_modrdn) ": txn1 id: %x\n",
		ltid->id(ltid), 0, 0 );

	opinfo.boi_oe.oe_key = bdb;
	opinfo.boi_txn = ltid;
	opinfo.boi_err = 0;
	opinfo.boi_acl_cache = op->o_do_not_cache;
	LDAP_SLIST_INSERT_HEAD( &op->o_extra, &opinfo.boi_oe, oe_next );

	/* get entry */
	rs->sr_err = bdb_dn2entry( op, ltid, &op->o_req_ndn, &ei, 1,
		&lock );

	switch( rs->sr_err ) {
	case 0:
	case DB_NOTFOUND:
		break;
	case DB_LOCK_DEADLOCK:
	case DB_LOCK_NOTGRANTED:
		goto retry;
	case LDAP_BUSY:
		rs->sr_text = "ldap server busy";
		goto return_results;
	default:
		rs->sr_err = LDAP_OTHER;
		rs->sr_text = "internal error";
		goto return_results;
	}

	e = ei->bei_e;
	/* FIXME: dn2entry() should return non-glue entry */
	if (( rs->sr_err == DB_NOTFOUND ) ||
		( !manageDSAit && e && is_entry_glue( e )))
	{
		if( e != NULL ) {
			rs->sr_matched = ch_strdup( e->e_dn );
			rs->sr_ref = is_entry_referral( e )
				? get_entry_referrals( op, e )
				: NULL;
			bdb_unlocked_cache_return_entry_r( &bdb->bi_cache, e);
			e = NULL;

		} else {
			rs->sr_ref = referral_rewrite( default_referral, NULL,
					&op->o_req_dn, LDAP_SCOPE_DEFAULT );
		}

		rs->sr_err = LDAP_REFERRAL;
		send_ldap_result( op, rs );

		ber_bvarray_free( rs->sr_ref );
		free( (char *)rs->sr_matched );
		rs->sr_ref = NULL;
		rs->sr_matched = NULL;

		goto done;
	}

	if ( get_assert( op ) &&
		( test_filter( op, e, get_assertion( op )) != LDAP_COMPARE_TRUE ))
	{
		rs->sr_err = LDAP_ASSERTION_FAILED;
		goto return_results;
	}

	/* check write on old entry */
	rs->sr_err = access_allowed( op, e, entry, NULL, ACL_WRITE, NULL );
	if ( ! rs->sr_err ) {
		switch( opinfo.boi_err ) {
		case DB_LOCK_DEADLOCK:
		case DB_LOCK_NOTGRANTED:
			goto retry;
		}

		Debug( LDAP_DEBUG_TRACE, "no access to entry\n", 0,
			0, 0 );
		rs->sr_text = "no write access to old entry";
		rs->sr_err = LDAP_INSUFFICIENT_ACCESS;
		goto return_results;
	}

#ifndef BDB_HIER
	rs->sr_err = bdb_cache_children( op, ltid, e );
	if ( rs->sr_err != DB_NOTFOUND ) {
		switch( rs->sr_err ) {
		case DB_LOCK_DEADLOCK:
		case DB_LOCK_NOTGRANTED:
			goto retry;
		case 0:
			Debug(LDAP_DEBUG_ARGS,
				"<=- " LDAP_XSTRING(bdb_modrdn)
				": non-leaf %s\n",
				op->o_req_dn.bv_val, 0, 0);
			rs->sr_err = LDAP_NOT_ALLOWED_ON_NONLEAF;
			rs->sr_text = "subtree rename not supported";
			break;
		default:
			Debug(LDAP_DEBUG_ARGS,
				"<=- " LDAP_XSTRING(bdb_modrdn)
				": has_children failed: %s (%d)\n",
				db_strerror(rs->sr_err), rs->sr_err, 0 );
			rs->sr_err = LDAP_OTHER;
			rs->sr_text = "internal error";
		}
		goto return_results;
	}
	ei->bei_state |= CACHE_ENTRY_NO_KIDS;
#endif

	if (!manageDSAit && is_entry_referral( e ) ) {
		/* parent is a referral, don't allow add */
		rs->sr_ref = get_entry_referrals( op, e );

		Debug( LDAP_DEBUG_TRACE, LDAP_XSTRING(bdb_modrdn)
			": entry %s is referral\n", e->e_dn, 0, 0 );

		rs->sr_err = LDAP_REFERRAL,
		rs->sr_matched = e->e_name.bv_val;
		send_ldap_result( op, rs );

		ber_bvarray_free( rs->sr_ref );
		rs->sr_ref = NULL;
		rs->sr_matched = NULL;
		goto done;
	}

	if ( be_issuffix( op->o_bd, &e->e_nname ) ) {
#ifdef BDB_MULTIPLE_SUFFIXES
		/* Allow renaming one suffix entry to another */
		p_ndn = slap_empty_bv;
#else
		/* There can only be one suffix entry */
		rs->sr_err = LDAP_NAMING_VIOLATION;
		rs->sr_text = "cannot rename suffix entry";
		goto return_results;
#endif
	} else {
		dnParent( &e->e_nname, &p_ndn );
	}
	np_ndn = &p_ndn;
	eip = ei->bei_parent;
	if ( eip && eip->bei_id ) {
		/* Make sure parent entry exist and we can write its 
		 * children.
		 */
		rs->sr_err = bdb_cache_find_id( op, ltid,
			eip->bei_id, &eip, 0, &plock );

		switch( rs->sr_err ) {
		case 0:
		case DB_NOTFOUND:
			break;
		case DB_LOCK_DEADLOCK:
		case DB_LOCK_NOTGRANTED:
			goto retry;
		case LDAP_BUSY:
			rs->sr_text = "ldap server busy";
			goto return_results;
		default:
			rs->sr_err = LDAP_OTHER;
			rs->sr_text = "internal error";
			goto return_results;
		}

		p = eip->bei_e;
		if( p == NULL) {
			Debug( LDAP_DEBUG_TRACE, LDAP_XSTRING(bdb_modrdn)
				": parent does not exist\n", 0, 0, 0);
			rs->sr_err = LDAP_OTHER;
			rs->sr_text = "old entry's parent does not exist";
			goto return_results;
		}
	} else {
		p = (Entry *)&slap_entry_root;
	}

	/* check parent for "children" acl */
	rs->sr_err = access_allowed( op, p,
		children, NULL,
		op->oq_modrdn.rs_newSup == NULL ?
			ACL_WRITE : ACL_WDEL,
		NULL );

	if ( !p_ndn.bv_len )
		p = NULL;

	if ( ! rs->sr_err ) {
		switch( opinfo.boi_err ) {
		case DB_LOCK_DEADLOCK:
		case DB_LOCK_NOTGRANTED:
			goto retry;
		}

		rs->sr_err = LDAP_INSUFFICIENT_ACCESS;
		Debug( LDAP_DEBUG_TRACE, "no access to parent\n", 0,
			0, 0 );
		rs->sr_text = "no write access to old parent's children";
		goto return_results;
	}

	Debug( LDAP_DEBUG_TRACE,
		LDAP_XSTRING(bdb_modrdn) ": wr to children "
		"of entry %s OK\n", p_ndn.bv_val, 0, 0 );
	
	if ( p_ndn.bv_val == slap_empty_bv.bv_val ) {
		p_dn = slap_empty_bv;
	} else {
		dnParent( &e->e_name, &p_dn );
	}

	Debug( LDAP_DEBUG_TRACE,
		LDAP_XSTRING(bdb_modrdn) ": parent dn=%s\n",
		p_dn.bv_val, 0, 0 );

	new_parent_dn = &p_dn;	/* New Parent unless newSuperior given */

	if ( op->oq_modrdn.rs_newSup != NULL ) {
		Debug( LDAP_DEBUG_TRACE, 
			LDAP_XSTRING(bdb_modrdn)
			": new parent \"%s\" requested...\n",
			op->oq_modrdn.rs_newSup->bv_val, 0, 0 );

		/*  newSuperior == oldParent? */
		if( dn_match( &p_ndn, op->oq_modrdn.rs_nnewSup ) ) {
			Debug( LDAP_DEBUG_TRACE, "bdb_back_modrdn: "
				"new parent \"%s\" same as the old parent \"%s\"\n",
				op->oq_modrdn.rs_newSup->bv_val, p_dn.bv_val, 0 );
			op->oq_modrdn.rs_newSup = NULL; /* ignore newSuperior */
		}
	}

	/* There's a BDB_MULTIPLE_SUFFIXES case here that this code doesn't
	 * support. E.g., two suffixes dc=foo,dc=com and dc=bar,dc=net.
	 * We do not allow modDN
	 *   dc=foo,dc=com
	 *    newrdn dc=bar
	 *    newsup dc=net
	 * and we probably should. But since MULTIPLE_SUFFIXES is deprecated
	 * I'm ignoring this problem for now.
	 */
	if ( op->oq_modrdn.rs_newSup != NULL ) {
		if ( op->oq_modrdn.rs_newSup->bv_len ) {
			np_dn = op->oq_modrdn.rs_newSup;
			np_ndn = op->oq_modrdn.rs_nnewSup;

			/* newSuperior == oldParent? - checked above */
			/* newSuperior == entry being moved?, if so ==> ERROR */
			if ( dnIsSuffix( np_ndn, &e->e_nname )) {
				rs->sr_err = LDAP_NO_SUCH_OBJECT;
				rs->sr_text = "new superior not found";
				goto return_results;
			}
			/* Get Entry with dn=newSuperior. Does newSuperior exist? */

			rs->sr_err = bdb_dn2entry( op, ltid, np_ndn,
				&neip, 0, &nplock );

			switch( rs->sr_err ) {
			case 0: np = neip->bei_e;
			case DB_NOTFOUND:
				break;
			case DB_LOCK_DEADLOCK:
			case DB_LOCK_NOTGRANTED:
				goto retry;
			case LDAP_BUSY:
				rs->sr_text = "ldap server busy";
				goto return_results;
			default:
				rs->sr_err = LDAP_OTHER;
				rs->sr_text = "internal error";
				goto return_results;
			}

			if( np == NULL) {
				Debug( LDAP_DEBUG_TRACE,
					LDAP_XSTRING(bdb_modrdn)
					": newSup(ndn=%s) not here!\n",
					np_ndn->bv_val, 0, 0);
				rs->sr_text = "new superior not found";
				rs->sr_err = LDAP_NO_SUCH_OBJECT;
				goto return_results;
			}

			Debug( LDAP_DEBUG_TRACE,
				LDAP_XSTRING(bdb_modrdn)
				": wr to new parent OK np=%p, id=%ld\n",
				(void *) np, (long) np->e_id, 0 );

			/* check newSuperior for "children" acl */
			rs->sr_err = access_allowed( op, np, children,
				NULL, ACL_WADD, NULL );

			if( ! rs->sr_err ) {
				switch( opinfo.boi_err ) {
				case DB_LOCK_DEADLOCK:
				case DB_LOCK_NOTGRANTED:
					goto retry;
				}

				Debug( LDAP_DEBUG_TRACE,
					LDAP_XSTRING(bdb_modrdn)
					": no wr to newSup children\n",
					0, 0, 0 );
				rs->sr_text = "no write access to new superior's children";
				rs->sr_err = LDAP_INSUFFICIENT_ACCESS;
				goto return_results;
			}

			if ( is_entry_alias( np ) ) {
				/* parent is an alias, don't allow add */
				Debug( LDAP_DEBUG_TRACE,
					LDAP_XSTRING(bdb_modrdn)
					": entry is alias\n",
					0, 0, 0 );
				rs->sr_text = "new superior is an alias";
				rs->sr_err = LDAP_ALIAS_PROBLEM;
				goto return_results;
			}

			if ( is_entry_referral( np ) ) {
				/* parent is a referral, don't allow add */
				Debug( LDAP_DEBUG_TRACE,
					LDAP_XSTRING(bdb_modrdn)
					": entry is referral\n",
					0, 0, 0 );
				rs->sr_text = "new superior is a referral";
				rs->sr_err = LDAP_OTHER;
				goto return_results;
			}

		} else {
			np_dn = NULL;

			/* no parent, modrdn entry directly under root */
			if ( be_issuffix( op->o_bd, (struct berval *)&slap_empty_bv )
				|| be_isupdate( op ) ) {
				np = (Entry *)&slap_entry_root;

				/* check parent for "children" acl */
				rs->sr_err = access_allowed( op, np,
					children, NULL, ACL_WADD, NULL );

				np = NULL;

				if ( ! rs->sr_err ) {
					switch( opinfo.boi_err ) {
					case DB_LOCK_DEADLOCK:
					case DB_LOCK_NOTGRANTED:
						goto retry;
					}

					rs->sr_err = LDAP_INSUFFICIENT_ACCESS;
					Debug( LDAP_DEBUG_TRACE, 
						"no access to new superior\n", 
						0, 0, 0 );
					rs->sr_text =
						"no write access to new superior's children";
					goto return_results;
				}
			}
		}

		Debug( LDAP_DEBUG_TRACE,
			LDAP_XSTRING(bdb_modrdn)
			": wr to new parent's children OK\n",
			0, 0, 0 );

		new_parent_dn = np_dn;
	}

	/* Build target dn and make sure target entry doesn't exist already. */
	if (!new_dn.bv_val) {
		build_new_dn( &new_dn, new_parent_dn, &op->oq_modrdn.rs_newrdn, NULL ); 
	}

	if (!new_ndn.bv_val) {
		struct berval bv = {0, NULL};
		dnNormalize( 0, NULL, NULL, &new_dn, &bv, op->o_tmpmemctx );
		ber_dupbv( &new_ndn, &bv );
		/* FIXME: why not call dnNormalize() w/o ctx? */
		op->o_tmpfree( bv.bv_val, op->o_tmpmemctx );
	}

	Debug( LDAP_DEBUG_TRACE, LDAP_XSTRING(bdb_modrdn) ": new ndn=%s\n",
		new_ndn.bv_val, 0, 0 );

	/* Shortcut the search */
	nei = neip ? neip : eip;
	rs->sr_err = bdb_cache_find_ndn ( op, ltid, &new_ndn, &nei );
	if ( nei ) bdb_cache_entryinfo_unlock( nei );
	switch( rs->sr_err ) {
	case DB_LOCK_DEADLOCK:
	case DB_LOCK_NOTGRANTED:
		goto retry;
	case DB_NOTFOUND:
		break;
	case 0:
		/* Allow rename to same DN */
		if ( nei == ei )
			break;
		rs->sr_err = LDAP_ALREADY_EXISTS;
		goto return_results;
	default:
		rs->sr_err = LDAP_OTHER;
		rs->sr_text = "internal error";
		goto return_results;
	}

	assert( op->orr_modlist != NULL );

	if( op->o_preread ) {
		if( preread_ctrl == NULL ) {
			preread_ctrl = &ctrls[num_ctrls++];
			ctrls[num_ctrls] = NULL;
		}
		if( slap_read_controls( op, rs, e,
			&slap_pre_read_bv, preread_ctrl ) )
		{
			Debug( LDAP_DEBUG_TRACE,        
				"<=- " LDAP_XSTRING(bdb_modrdn)
				": pre-read failed!\n", 0, 0, 0 );
			if ( op->o_preread & SLAP_CONTROL_CRITICAL ) {
				/* FIXME: is it correct to abort
				 * operation if control fails? */
				goto return_results;
			}
		}                   
	}

	/* nested transaction */
	rs->sr_err = TXN_BEGIN( bdb->bi_dbenv, ltid, &lt2, bdb->bi_db_opflags );
	rs->sr_text = NULL;
	if( rs->sr_err != 0 ) {
		Debug( LDAP_DEBUG_TRACE,
			LDAP_XSTRING(bdb_modrdn)
			": txn_begin(2) failed: %s (%d)\n",
			db_strerror(rs->sr_err), rs->sr_err, 0 );
		rs->sr_err = LDAP_OTHER;
		rs->sr_text = "internal error";
		goto return_results;
	}
	Debug( LDAP_DEBUG_TRACE, LDAP_XSTRING(bdb_modrdn) ": txn2 id: %x\n",
		lt2->id(lt2), 0, 0 );

	/* delete old DN */
	rs->sr_err = bdb_dn2id_delete( op, lt2, eip, e );
	if ( rs->sr_err != 0 ) {
		Debug(LDAP_DEBUG_TRACE,
			"<=- " LDAP_XSTRING(bdb_modrdn)
			": dn2id del failed: %s (%d)\n",
			db_strerror(rs->sr_err), rs->sr_err, 0 );
		switch( rs->sr_err ) {
		case DB_LOCK_DEADLOCK:
		case DB_LOCK_NOTGRANTED:
			goto retry;
		}
		rs->sr_err = LDAP_OTHER;
		rs->sr_text = "DN index delete fail";
		goto return_results;
	}

	/* copy the entry, then override some fields */
	dummy = *e;
	dummy.e_name = new_dn;
	dummy.e_nname = new_ndn;
	dummy.e_attrs = NULL;

	/* add new DN */
	rs->sr_err = bdb_dn2id_add( op, lt2, neip ? neip : eip, &dummy );
	if ( rs->sr_err != 0 ) {
		Debug(LDAP_DEBUG_TRACE,
			"<=- " LDAP_XSTRING(bdb_modrdn)
			": dn2id add failed: %s (%d)\n",
			db_strerror(rs->sr_err), rs->sr_err, 0 );
		switch( rs->sr_err ) {
		case DB_LOCK_DEADLOCK:
		case DB_LOCK_NOTGRANTED:
			goto retry;
		}
		rs->sr_err = LDAP_OTHER;
		rs->sr_text = "DN index add failed";
		goto return_results;
	}

	dummy.e_attrs = e->e_attrs;

	/* modify entry */
	rs->sr_err = bdb_modify_internal( op, lt2, op->orr_modlist, &dummy,
		&rs->sr_text, textbuf, textlen );
	if( rs->sr_err != LDAP_SUCCESS ) {
		Debug(LDAP_DEBUG_TRACE,
			"<=- " LDAP_XSTRING(bdb_modrdn)
			": modify failed: %s (%d)\n",
			db_strerror(rs->sr_err), rs->sr_err, 0 );
		if ( ( rs->sr_err == LDAP_INSUFFICIENT_ACCESS ) && opinfo.boi_err ) {
			rs->sr_err = opinfo.boi_err;
		}
		if ( dummy.e_attrs == e->e_attrs ) dummy.e_attrs = NULL;
		switch( rs->sr_err ) {
		case DB_LOCK_DEADLOCK:
		case DB_LOCK_NOTGRANTED:
			goto retry;
		}
		goto return_results;
	}

	/* id2entry index */
	rs->sr_err = bdb_id2entry_update( op->o_bd, lt2, &dummy );
	if ( rs->sr_err != 0 ) {
		Debug(LDAP_DEBUG_TRACE,
			"<=- " LDAP_XSTRING(bdb_modrdn)
			": id2entry failed: %s (%d)\n",
			db_strerror(rs->sr_err), rs->sr_err, 0 );
		switch( rs->sr_err ) {
		case DB_LOCK_DEADLOCK:
		case DB_LOCK_NOTGRANTED:
			goto retry;
		}
		rs->sr_err = LDAP_OTHER;
		rs->sr_text = "entry update failed";
		goto return_results;
	}

	if ( p_ndn.bv_len != 0 ) {
		parent_is_glue = is_entry_glue(p);
		rs->sr_err = bdb_cache_children( op, lt2, p );
		if ( rs->sr_err != DB_NOTFOUND ) {
			switch( rs->sr_err ) {
			case DB_LOCK_DEADLOCK:
			case DB_LOCK_NOTGRANTED:
				goto retry;
			case 0:
				break;
			default:
				Debug(LDAP_DEBUG_ARGS,
					"<=- " LDAP_XSTRING(bdb_modrdn)
					": has_children failed: %s (%d)\n",
					db_strerror(rs->sr_err), rs->sr_err, 0 );
				rs->sr_err = LDAP_OTHER;
				rs->sr_text = "internal error";
				goto return_results;
			}
			parent_is_leaf = 1;
		}
		bdb_unlocked_cache_return_entry_r(&bdb->bi_cache, p);
		p = NULL;
	}

	if ( TXN_COMMIT( lt2, 0 ) != 0 ) {
		rs->sr_err = LDAP_OTHER;
		rs->sr_text = "txn_commit(2) failed";
		goto return_results;
	}

	if( op->o_postread ) {
		if( postread_ctrl == NULL ) {
			postread_ctrl = &ctrls[num_ctrls++];
			ctrls[num_ctrls] = NULL;
		}
		if( slap_read_controls( op, rs, &dummy,
			&slap_post_read_bv, postread_ctrl ) )
		{
			Debug( LDAP_DEBUG_TRACE,        
				"<=- " LDAP_XSTRING(bdb_modrdn)
				": post-read failed!\n", 0, 0, 0 );
			if ( op->o_postread & SLAP_CONTROL_CRITICAL ) {
				/* FIXME: is it correct to abort
				 * operation if control fails? */
				goto return_results;
			}
		}                   
	}

	if( op->o_noop ) {
		if(( rs->sr_err=TXN_ABORT( ltid )) != 0 ) {
			rs->sr_text = "txn_abort (no-op) failed";
		} else {
			rs->sr_err = LDAP_X_NO_OPERATION;
			ltid = NULL;
			/* Only free attrs if they were dup'd.  */
			if ( dummy.e_attrs == e->e_attrs ) dummy.e_attrs = NULL;
			goto return_results;
		}

	} else {
		rc = bdb_cache_modrdn( bdb, e, &op->orr_nnewrdn, &dummy, neip,
			ltid, &lock );
		switch( rc ) {
		case DB_LOCK_DEADLOCK:
		case DB_LOCK_NOTGRANTED:
			goto retry;
		}
		dummy.e_attrs = NULL;
		new_dn.bv_val = NULL;
		new_ndn.bv_val = NULL;

		if(( rs->sr_err=TXN_COMMIT( ltid, 0 )) != 0 ) {
			rs->sr_text = "txn_commit failed";
		} else {
			rs->sr_err = LDAP_SUCCESS;
		}
	}
 
	ltid = NULL;
	LDAP_SLIST_REMOVE( &op->o_extra, &opinfo.boi_oe, OpExtra, oe_next );
	opinfo.boi_oe.oe_key = NULL;
 
	if( rs->sr_err != LDAP_SUCCESS ) {
		Debug( LDAP_DEBUG_TRACE,
			LDAP_XSTRING(bdb_modrdn) ": %s : %s (%d)\n",
			rs->sr_text, db_strerror(rs->sr_err), rs->sr_err );
		rs->sr_err = LDAP_OTHER;

		goto return_results;
	}

	Debug(LDAP_DEBUG_TRACE,
		LDAP_XSTRING(bdb_modrdn)
		": rdn modified%s id=%08lx dn=\"%s\"\n",
		op->o_noop ? " (no-op)" : "",
		dummy.e_id, op->o_req_dn.bv_val );
	rs->sr_text = NULL;
	if( num_ctrls ) rs->sr_ctrls = ctrls;

return_results:
	if ( dummy.e_attrs ) {
		attrs_free( dummy.e_attrs );
	}
	send_ldap_result( op, rs );

	if( rs->sr_err == LDAP_SUCCESS && bdb->bi_txn_cp_kbyte ) {
		TXN_CHECKPOINT( bdb->bi_dbenv,
			bdb->bi_txn_cp_kbyte, bdb->bi_txn_cp_min, 0 );
	}
	
	if ( rs->sr_err == LDAP_SUCCESS && parent_is_glue && parent_is_leaf ) {
		op->o_delete_glue_parent = 1;
	}

done:
	slap_graduate_commit_csn( op );

	if( new_dn.bv_val != NULL ) free( new_dn.bv_val );
	if( new_ndn.bv_val != NULL ) free( new_ndn.bv_val );

	/* LDAP v3 Support */
	if( np != NULL ) {
		/* free new parent and reader lock */
		bdb_unlocked_cache_return_entry_r(&bdb->bi_cache, np);
	}

	if( p != NULL ) {
		/* free parent and reader lock */
		bdb_unlocked_cache_return_entry_r(&bdb->bi_cache, p);
	}

	/* free entry */
	if( e != NULL ) {
		bdb_unlocked_cache_return_entry_w( &bdb->bi_cache, e);
	}

	if( ltid != NULL ) {
		TXN_ABORT( ltid );
	}
	if ( opinfo.boi_oe.oe_key ) {
		LDAP_SLIST_REMOVE( &op->o_extra, &opinfo.boi_oe, OpExtra, oe_next );
	}

	if( preread_ctrl != NULL && (*preread_ctrl) != NULL ) {
		slap_sl_free( (*preread_ctrl)->ldctl_value.bv_val, op->o_tmpmemctx );
		slap_sl_free( *preread_ctrl, op->o_tmpmemctx );
	}
	if( postread_ctrl != NULL && (*postread_ctrl) != NULL ) {
		slap_sl_free( (*postread_ctrl)->ldctl_value.bv_val, op->o_tmpmemctx );
		slap_sl_free( *postread_ctrl, op->o_tmpmemctx );
	}
	return rs->sr_err;
}
Exemple #6
0
static int
slap_parse_refresh(
	struct berval	*in,
	struct berval	*ndn,
	time_t		*ttl,
	const char	**text,
	void		*ctx )
{
	int			rc = LDAP_SUCCESS;
	ber_tag_t		tag;
	ber_len_t		len = -1;
	BerElementBuffer	berbuf;
	BerElement		*ber = (BerElement *)&berbuf;
	struct berval		reqdata = BER_BVNULL;
	int			tmp;

	*text = NULL;

	if ( ndn ) {
		BER_BVZERO( ndn );
	}

	if ( in == NULL || in->bv_len == 0 ) {
		*text = "empty request data field in refresh exop";
		return LDAP_PROTOCOL_ERROR;
	}

	ber_dupbv_x( &reqdata, in, ctx );

	/* ber_init2 uses reqdata directly, doesn't allocate new buffers */
	ber_init2( ber, &reqdata, 0 );

	tag = ber_scanf( ber, "{" /*}*/ );

	if ( tag == LBER_ERROR ) {
		Log0( LDAP_DEBUG_TRACE, LDAP_LEVEL_ERR,
			"slap_parse_refresh: decoding error.\n" );
		goto decoding_error;
	}

	tag = ber_peek_tag( ber, &len );
	if ( tag != LDAP_TAG_EXOP_REFRESH_REQ_DN ) {
		Log0( LDAP_DEBUG_TRACE, LDAP_LEVEL_ERR,
			"slap_parse_refresh: decoding error.\n" );
		goto decoding_error;
	}

	if ( ndn ) {
		struct berval	dn;

		tag = ber_scanf( ber, "m", &dn );
		if ( tag == LBER_ERROR ) {
			Log0( LDAP_DEBUG_TRACE, LDAP_LEVEL_ERR,
				"slap_parse_refresh: DN parse failed.\n" );
			goto decoding_error;
		}

		rc = dnNormalize( 0, NULL, NULL, &dn, ndn, ctx );
		if ( rc != LDAP_SUCCESS ) {
			*text = "invalid DN in refresh exop request data";
			goto done;
		}

	} else {
		tag = ber_scanf( ber, "x" /* "m" */ );
		if ( tag == LBER_DEFAULT ) {
			goto decoding_error;
		}
	}

	tag = ber_peek_tag( ber, &len );

	if ( tag != LDAP_TAG_EXOP_REFRESH_REQ_TTL ) {
		Log0( LDAP_DEBUG_TRACE, LDAP_LEVEL_ERR,
			"slap_parse_refresh: decoding error.\n" );
		goto decoding_error;
	}

	tag = ber_scanf( ber, "i", &tmp );
	if ( tag == LBER_ERROR ) {
		Log0( LDAP_DEBUG_TRACE, LDAP_LEVEL_ERR,
			"slap_parse_refresh: TTL parse failed.\n" );
		goto decoding_error;
	}

	if ( ttl ) {
		*ttl = tmp;
	}

	tag = ber_peek_tag( ber, &len );

	if ( tag != LBER_DEFAULT || len != 0 ) {
decoding_error:;
		Log1( LDAP_DEBUG_TRACE, LDAP_LEVEL_ERR,
			"slap_parse_refresh: decoding error, len=%ld\n",
			(long)len );
		rc = LDAP_PROTOCOL_ERROR;
		*text = "data decoding error";

done:;
		if ( ndn && !BER_BVISNULL( ndn ) ) {
			slap_sl_free( ndn->bv_val, ctx );
			BER_BVZERO( ndn );
		}
	}

	if ( !BER_BVISNULL( &reqdata ) ) {
		ber_memfree_x( reqdata.bv_val, ctx );
	}

	return rc;
}
Exemple #7
0
static int
aci_group_member (
	struct berval		*subj,
	const struct berval	*defgrpoc,
	const struct berval	*defgrpat,
	Operation		*op,
	Entry			*e,
	int			nmatch,
	regmatch_t		*matches
)
{
	struct berval		subjdn;
	struct berval		grpoc;
	struct berval		grpat;
	ObjectClass		*grp_oc = NULL;
	AttributeDescription	*grp_ad = NULL;
	const char		*text;
	int			rc;

	/* format of string is "{group|role}/objectClassValue/groupAttrName" */
	if ( acl_get_part( subj, 0, '/', &subjdn ) < 0 ) {
		return 0;
	}

	if ( acl_get_part( subj, 1, '/', &grpoc ) < 0 ) {
		grpoc = *defgrpoc;
	}

	if ( acl_get_part( subj, 2, '/', &grpat ) < 0 ) {
		grpat = *defgrpat;
	}

	rc = slap_bv2ad( &grpat, &grp_ad, &text );
	if ( rc != LDAP_SUCCESS ) {
		rc = 0;
		goto done;
	}
	rc = 0;

	grp_oc = oc_bvfind( &grpoc );

	if ( grp_oc != NULL && grp_ad != NULL ) {
		char		buf[ ACI_BUF_SIZE ];
		struct berval	bv, ndn;
		AclRegexMatches amatches = { 0 };

		amatches.dn_count = nmatch;
		memcpy( amatches.dn_data, matches, sizeof( amatches.dn_data ) );

		bv.bv_len = sizeof( buf ) - 1;
		bv.bv_val = (char *)&buf;
		if ( acl_string_expand( &bv, &subjdn,
				&e->e_nname, NULL, &amatches ) )
		{
			rc = LDAP_OTHER;
			goto done;
		}

		if ( dnNormalize( 0, NULL, NULL, &bv, &ndn, op->o_tmpmemctx ) == LDAP_SUCCESS )
		{
			rc = ( backend_group( op, e, &ndn, &op->o_ndn,
				grp_oc, grp_ad ) == 0 );
			slap_sl_free( ndn.bv_val, op->o_tmpmemctx );
		}
	}

done:
	return rc;
}
Exemple #8
0
static int
vc_exop(
	Operation	*op,
	SlapReply	*rs )
{
	int rc = LDAP_SUCCESS;
	ber_tag_t tag;
	ber_len_t len = -1;
	BerElementBuffer berbuf;
	BerElement *ber = (BerElement *)&berbuf;
	struct berval reqdata = BER_BVNULL;

	struct berval cookie = BER_BVNULL;
	struct berval bdn = BER_BVNULL;
	ber_tag_t authtag;
	struct berval cred = BER_BVNULL;
	struct berval ndn = BER_BVNULL;
	struct berval mechanism = BER_BVNULL;

	vc_conn_t *conn = NULL;
	vc_cb_t vc = { 0 };
	slap_callback sc = { 0 };
	SlapReply rs2 = { 0 };

	if ( op->ore_reqdata == NULL || op->ore_reqdata->bv_len == 0 ) {
		rs->sr_text = "empty request data field in VerifyCredentials exop";
		return LDAP_PROTOCOL_ERROR;
	}

	/* optimistic */
	rs->sr_err = LDAP_SUCCESS;

	ber_dupbv_x( &reqdata, op->ore_reqdata, op->o_tmpmemctx );

	/* ber_init2 uses reqdata directly, doesn't allocate new buffers */
	ber_init2( ber, &reqdata, 0 );

	tag = ber_scanf( ber, "{" /*}*/ );
	if ( tag != LBER_SEQUENCE ) {
		rs->sr_err = LDAP_PROTOCOL_ERROR;
		goto done;
	}

	tag = ber_peek_tag( ber, &len );
	if ( tag == LDAP_TAG_EXOP_VERIFY_CREDENTIALS_COOKIE ) {
		/*
		 * cookie: the pointer to the connection
		 * of this operation
		 */

		ber_scanf( ber, "m", &cookie );
		if ( cookie.bv_len != sizeof(Connection *) ) {
			rs->sr_err = LDAP_PROTOCOL_ERROR;
			goto done;
		}
	}

	/* DN, authtag */
	tag = ber_scanf( ber, "mt", &bdn, &authtag );
	if ( tag == LBER_ERROR ) {
		rs->sr_err = LDAP_PROTOCOL_ERROR;
		goto done;
	}

	rc = dnNormalize( 0, NULL, NULL, &bdn, &ndn, op->o_tmpmemctx );
	if ( rc != LDAP_SUCCESS ) {
		rs->sr_err = LDAP_PROTOCOL_ERROR;
		goto done;
	}

	switch ( authtag ) {
	case LDAP_AUTH_SIMPLE:
		/* cookie only makes sense for SASL bind (so far) */
		if ( !BER_BVISNULL( &cookie ) ) {
			rs->sr_err = LDAP_PROTOCOL_ERROR;
			goto done;
		}

		tag = ber_scanf( ber, "m", &cred );
		if ( tag == LBER_ERROR ) {
			rs->sr_err = LDAP_PROTOCOL_ERROR;
			goto done;
		}
		break;

	case LDAP_AUTH_SASL:
		tag = ber_scanf( ber, "{s" /*}*/ , &mechanism );
		if ( tag == LBER_ERROR || 
			BER_BVISNULL( &mechanism ) || BER_BVISEMPTY( &mechanism ) )
		{
			rs->sr_err = LDAP_PROTOCOL_ERROR;
			goto done;
		}

		tag = ber_peek_tag( ber, &len );
		if ( tag == LBER_OCTETSTRING ) {
			ber_scanf( ber, "m", &cred );
		}

		tag = ber_scanf( ber, /*{*/ "}" );
		break;

	default:
		rs->sr_err = LDAP_PROTOCOL_ERROR;
		goto done;
	}

	if ( !BER_BVISNULL( &cookie ) ) {
		vc_conn_t tmp = { 0 };

		AC_MEMCPY( (char *)&tmp.conn, (const char *)cookie.bv_val, cookie.bv_len );
		ldap_pvt_thread_mutex_lock( &vc_mutex );
		conn = (vc_conn_t *)avl_find( vc_tree, (caddr_t)&tmp, vc_conn_cmp );
		if ( conn == NULL || ( conn != NULL && conn->refcnt != 0 ) ) {
			conn = NULL;
			ldap_pvt_thread_mutex_unlock( &vc_mutex );
			rs->sr_err = LDAP_PROTOCOL_ERROR;
			goto done;
		}
		conn->refcnt++;
		ldap_pvt_thread_mutex_unlock( &vc_mutex );

	} else {
		void *thrctx;

		conn = (vc_conn_t *)SLAP_CALLOC( 1, sizeof( vc_conn_t ) );
		conn->refcnt = 1;

		thrctx = ldap_pvt_thread_pool_context();
		connection_fake_init2( &conn->connbuf, &conn->opbuf, thrctx, 0 );
		conn->op = &conn->opbuf.ob_op;
		snprintf( conn->op->o_log_prefix, sizeof( conn->op->o_log_prefix ),
			"%s VERIFYCREDENTIALS", op->o_log_prefix );
	}

	conn->op->o_tag = LDAP_REQ_BIND;
	memset( &conn->op->oq_bind, 0, sizeof( conn->op->oq_bind ) );
	conn->op->o_req_dn = ndn;
	conn->op->o_req_ndn = ndn;
	conn->op->o_protocol = LDAP_VERSION3;
	conn->op->orb_method = authtag;
	conn->op->o_callback = &sc;

	/* TODO: controls */
	tag = ber_peek_tag( ber, &len );
	if ( tag == LDAP_TAG_EXOP_VERIFY_CREDENTIALS_CONTROLS ) {
		conn->op->o_ber = ber;
		rc = get_ctrls2( conn->op, &rs2, 0, LDAP_TAG_EXOP_VERIFY_CREDENTIALS_CONTROLS );
		if ( rc != LDAP_SUCCESS ) {
			rs->sr_err = LDAP_PROTOCOL_ERROR;
			goto done;
		}
	}

	tag = ber_skip_tag( ber, &len );
	if ( len || tag != LBER_DEFAULT ) {
		rs->sr_err = LDAP_PROTOCOL_ERROR;
		goto done;
	}

	switch ( authtag ) {
	case LDAP_AUTH_SIMPLE:
		break;

	case LDAP_AUTH_SASL:
		conn->op->orb_mech = mechanism;
		break;
	}

	conn->op->orb_cred = cred;
	sc.sc_response = vc_cb;
	sc.sc_private = &vc;

	conn->op->o_bd = frontendDB;
	rs->sr_err = frontendDB->be_bind( conn->op, &rs2 );

	if ( conn->op->o_conn->c_sasl_bind_in_progress ) {
		rc = vc_create_response( conn, rs2.sr_err, rs2.sr_text,
			!BER_BVISEMPTY( &vc.sasldata ) ? &vc.sasldata : NULL,
			NULL,
			vc.ctrls, &rs->sr_rspdata );

	} else {
		rc = vc_create_response( NULL, rs2.sr_err, rs2.sr_text,
			NULL,
			&conn->op->o_conn->c_dn,
			vc.ctrls, &rs->sr_rspdata );
	}

	if ( rc != 0 ) {
		rs->sr_err = LDAP_OTHER;
		goto done;
	}

	if ( !BER_BVISNULL( &conn->op->o_conn->c_dn ) &&
		conn->op->o_conn->c_dn.bv_val != conn->op->o_conn->c_ndn.bv_val )
		ber_memfree( conn->op->o_conn->c_dn.bv_val );
	if ( !BER_BVISNULL( &conn->op->o_conn->c_ndn ) )
		ber_memfree( conn->op->o_conn->c_ndn.bv_val );

done:;
	if ( conn ) {
		if ( conn->op->o_conn->c_sasl_bind_in_progress ) {
			if ( conn->conn == NULL ) {
				conn->conn = conn;
				conn->refcnt--;
				ldap_pvt_thread_mutex_lock( &vc_mutex );
				rc = avl_insert( &vc_tree, (caddr_t)conn,
					vc_conn_cmp, vc_conn_dup );
				ldap_pvt_thread_mutex_unlock( &vc_mutex );
				assert( rc == 0 );

			} else {
				ldap_pvt_thread_mutex_lock( &vc_mutex );
				conn->refcnt--;
				ldap_pvt_thread_mutex_unlock( &vc_mutex );
			}

		} else {
			if ( conn->conn != NULL ) {
				vc_conn_t *tmp;

				ldap_pvt_thread_mutex_lock( &vc_mutex );
				tmp = avl_delete( &vc_tree, (caddr_t)conn, vc_conn_cmp );
				ldap_pvt_thread_mutex_unlock( &vc_mutex );
			}
			SLAP_FREE( conn );
		}
	}

	if ( vc.ctrls ) {
		ldap_controls_free( vc.ctrls );
		vc.ctrls = NULL;
	}

	if ( !BER_BVISNULL( &ndn ) ) {
		op->o_tmpfree( ndn.bv_val, op->o_tmpmemctx );
		BER_BVZERO( &ndn );
	}

	op->o_tmpfree( reqdata.bv_val, op->o_tmpmemctx );
	BER_BVZERO( &reqdata );

        return rs->sr_err;
}
Exemple #9
0
static int
valsort_cf_func(ConfigArgs *c) {
	slap_overinst *on = (slap_overinst *)c->bi;
	valsort_info vitmp, *vi;
	const char *text = NULL;
	int i, is_numeric;
	struct berval bv = BER_BVNULL;

	if ( c->op == SLAP_CONFIG_EMIT ) {
		for ( vi = on->on_bi.bi_private; vi; vi = vi->vi_next ) {
			struct berval bv2 = BER_BVNULL, bvret;
			char *ptr;
			int len;
			
			len = vi->vi_ad->ad_cname.bv_len + 1 + vi->vi_dn.bv_len + 2;
			i = vi->vi_sort;
			if ( i & VALSORT_WEIGHTED ) {
				enum_to_verb( sorts, VALSORT_WEIGHTED, &bv2 );
				len += bv2.bv_len + 1;
				i ^= VALSORT_WEIGHTED;
			}
			if ( i ) {
				enum_to_verb( sorts, i, &bv );
				len += bv.bv_len + 1;
			}
			bvret.bv_val = ch_malloc( len+1 );
			bvret.bv_len = len;

			ptr = lutil_strcopy( bvret.bv_val, vi->vi_ad->ad_cname.bv_val );
			*ptr++ = ' ';
			*ptr++ = '"';
			ptr = lutil_strcopy( ptr, vi->vi_dn.bv_val );
			*ptr++ = '"';
			if ( vi->vi_sort & VALSORT_WEIGHTED ) {
				*ptr++ = ' ';
				ptr = lutil_strcopy( ptr, bv2.bv_val );
			}
			if ( i ) {
				*ptr++ = ' ';
				strcpy( ptr, bv.bv_val );
			}
			ber_bvarray_add( &c->rvalue_vals, &bvret );
		}
		i = ( c->rvalue_vals != NULL ) ? 0 : 1;
		return i;
	} else if ( c->op == LDAP_MOD_DELETE ) {
		if ( c->valx < 0 ) {
			for ( vi = on->on_bi.bi_private; vi; vi = on->on_bi.bi_private ) {
				on->on_bi.bi_private = vi->vi_next;
				ch_free( vi->vi_dn.bv_val );
				ch_free( vi );
			}
		} else {
			valsort_info **prev;

			for (i=0, prev = (valsort_info **)&on->on_bi.bi_private,
				vi = *prev; vi && i<c->valx;
				prev = &vi->vi_next, vi = vi->vi_next, i++ );
			(*prev)->vi_next = vi->vi_next;
			ch_free( vi->vi_dn.bv_val );
			ch_free( vi );
		}
		return 0;
	}
	vitmp.vi_ad = NULL;
	i = slap_str2ad( c->argv[1], &vitmp.vi_ad, &text );
	if ( i ) {
		snprintf( c->cr_msg, sizeof( c->cr_msg), "<%s> %s", c->argv[0], text );
		Debug( LDAP_DEBUG_ANY, "%s: %s (%s)!\n",
			c->log, c->cr_msg, c->argv[1] );
		return(1);
	}
	if ( is_at_single_value( vitmp.vi_ad->ad_type )) {
		snprintf( c->cr_msg, sizeof( c->cr_msg ), "<%s> %s is single-valued, ignoring", c->argv[0],
			vitmp.vi_ad->ad_cname.bv_val );
		Debug( LDAP_DEBUG_ANY, "%s: %s (%s)!\n",
			c->log, c->cr_msg, c->argv[1] );
		return(0);
	}
	is_numeric = ( vitmp.vi_ad->ad_type->sat_syntax == syn_numericString ||
		vitmp.vi_ad->ad_type->sat_syntax == slap_schema.si_syn_integer ) ? 1
		: 0;
	ber_str2bv( c->argv[2], 0, 0, &bv );
	i = dnNormalize( 0, NULL, NULL, &bv, &vitmp.vi_dn, NULL );
	if ( i ) {
		snprintf( c->cr_msg, sizeof( c->cr_msg ), "<%s> unable to normalize DN", c->argv[0] );
		Debug( LDAP_DEBUG_ANY, "%s: %s (%s)!\n",
			c->log, c->cr_msg, c->argv[2] );
		return(1);
	}
	i = verb_to_mask( c->argv[3], sorts );
	if ( BER_BVISNULL( &sorts[i].word )) {
		snprintf( c->cr_msg, sizeof( c->cr_msg ), "<%s> unrecognized sort type", c->argv[0] );
		Debug( LDAP_DEBUG_ANY, "%s: %s (%s)!\n",
			c->log, c->cr_msg, c->argv[3] );
		return(1);
	}
	vitmp.vi_sort = sorts[i].mask;
	if ( sorts[i].mask == VALSORT_WEIGHTED && c->argc == 5 ) {
		i = verb_to_mask( c->argv[4], sorts );
		if ( BER_BVISNULL( &sorts[i].word )) {
			snprintf( c->cr_msg, sizeof( c->cr_msg ), "<%s> unrecognized sort type", c->argv[0] );
			Debug( LDAP_DEBUG_ANY, "%s: %s (%s)!\n",
				c->log, c->cr_msg, c->argv[4] );
			return(1);
		}
		vitmp.vi_sort |= sorts[i].mask;
	}
	if (( vitmp.vi_sort & VALSORT_NUMERIC ) && !is_numeric ) {
		snprintf( c->cr_msg, sizeof( c->cr_msg ), "<%s> numeric sort specified for non-numeric syntax",
			c->argv[0] );
		Debug( LDAP_DEBUG_ANY, "%s: %s (%s)!\n",
			c->log, c->cr_msg, c->argv[1] );
		return(1);
	}
	vi = ch_malloc( sizeof(valsort_info) );
	*vi = vitmp;
	vi->vi_next = on->on_bi.bi_private;
	on->on_bi.bi_private = vi;
	return 0;
}
Exemple #10
0
static int
allop_db_config(
	BackendDB	*be,
	const char	*fname,
	int		lineno,
	int		argc,
	char		**argv )
{
	slap_overinst	*on = (slap_overinst *)be->bd_info;
	allop_t		*ao = (allop_t *)on->on_bi.bi_private;

	if ( strcasecmp( argv[ 0 ], "allop-uri" ) == 0 ) {
		LDAPURLDesc	*lud;
		struct berval	dn,
				ndn;
		int		scope,
				rc = LDAP_SUCCESS;

		if ( argc != 2 ) {
			fprintf( stderr, "%s line %d: "
				"need exactly 1 arg "
				"in \"allop-uri <ldapURI>\" "
				"directive.\n",
				fname, lineno );
			return 1;
		}

		if ( ldap_url_parse( argv[ 1 ], &lud ) != LDAP_URL_SUCCESS ) {
			return -1;
		}

		scope = lud->lud_scope;
		if ( scope == LDAP_SCOPE_DEFAULT ) {
			scope = LDAP_SCOPE_BASE;
		}

		if ( lud->lud_dn == NULL || lud->lud_dn[ 0 ] == '\0' ) {
			if ( scope == LDAP_SCOPE_BASE ) {
				BER_BVZERO( &ndn );

			} else {
				ber_str2bv( "", 0, 1, &ndn );
			}

		} else {

			ber_str2bv( lud->lud_dn, 0, 0, &dn );
			rc = dnNormalize( 0, NULL, NULL, &dn, &ndn, NULL );
		}

		ldap_free_urldesc( lud );
		if ( rc != LDAP_SUCCESS ) {
			return -1;
		}

		if ( BER_BVISNULL( &ndn ) ) {
			/* rootDSE */
			if ( ao != NULL ) {
				ch_free( ao->ao_ndn.bv_val );
				ch_free( ao );
				on->on_bi.bi_private = NULL;
			}

		} else {
			if ( ao == NULL ) {
				ao = ch_calloc( 1, sizeof( allop_t ) );
				on->on_bi.bi_private = (void *)ao;

			} else {
				ch_free( ao->ao_ndn.bv_val );
			}

			ao->ao_ndn = ndn;
			ao->ao_scope = scope;
		}

	} else {
		return SLAP_CONF_UNKNOWN;
	}

	return 0;
}
Exemple #11
0
static int
constraint_cf_gen( ConfigArgs *c )
{
	slap_overinst *on = (slap_overinst *)(c->bi);
	constraint *cn = on->on_bi.bi_private, *cp;
	struct berval bv;
	int i, rc = 0;
	constraint ap = { NULL };
	const char *text = NULL;
	
	switch ( c->op ) {
	case SLAP_CONFIG_EMIT:
		switch (c->type) {
		case CONSTRAINT_ATTRIBUTE:
			for (cp=cn; cp; cp=cp->ap_next) {
				char *s;
				char *tstr = NULL;
				int quotes = 0;
				int j;

				bv.bv_len = STRLENOF("  ");
				for (j = 0; cp->ap[j]; j++) {
					bv.bv_len += cp->ap[j]->ad_cname.bv_len;
				}

				/* room for commas */
				bv.bv_len += j - 1;

				if (cp->re) {
					tstr = REGEX_STR;
				} else if (cp->lud) {
					tstr = URI_STR;
					quotes = 1;
				} else if (cp->set) {
					tstr = SET_STR;
					quotes = 1;
				} else if (cp->size) {
					tstr = SIZE_STR;
				} else if (cp->count) {
					tstr = COUNT_STR;
				}

				bv.bv_len += strlen(tstr);
				bv.bv_len += cp->val.bv_len + 2*quotes;

				if (cp->restrict_lud != NULL) {
					bv.bv_len += cp->restrict_val.bv_len + STRLENOF(" restrict=\"\"");
				}

				s = bv.bv_val = ch_malloc(bv.bv_len + 1);

				s = lutil_strncopy( s, cp->ap[0]->ad_cname.bv_val, cp->ap[0]->ad_cname.bv_len );
				for (j = 1; cp->ap[j]; j++) {
					*s++ = ',';
					s = lutil_strncopy( s, cp->ap[j]->ad_cname.bv_val, cp->ap[j]->ad_cname.bv_len );
				}
				*s++ = ' ';
				s = lutil_strcopy( s, tstr );
				*s++ = ' ';
				if ( quotes ) *s++ = '"';
				s = lutil_strncopy( s, cp->val.bv_val, cp->val.bv_len );
				if ( quotes ) *s++ = '"';
				if (cp->restrict_lud != NULL) {
					s = lutil_strcopy( s, " restrict=\"" );
					s = lutil_strncopy( s, cp->restrict_val.bv_val, cp->restrict_val.bv_len );
					*s++ = '"';
				}
				*s = '\0';

				rc = value_add_one( &c->rvalue_vals, &bv );
				if (rc == LDAP_SUCCESS)
					rc = value_add_one( &c->rvalue_nvals, &bv );
				ch_free(bv.bv_val);
				if (rc) return rc;
			}
			break;
		default:
			abort();
			break;
		}
		break;
	case LDAP_MOD_DELETE:
		switch (c->type) {
		case CONSTRAINT_ATTRIBUTE:
			if (!cn) break; /* nothing to do */
					
			if (c->valx < 0) {
				/* zap all constraints */
				while (cn) {
					cp = cn->ap_next;
					constraint_free( cn, 1 );
					cn = cp;
				}
						
				on->on_bi.bi_private = NULL;
			} else {
				constraint **cpp;
						
				/* zap constraint numbered 'valx' */
				for(i=0, cp = cn, cpp = &cn;
					(cp) && (i<c->valx);
					i++, cpp = &cp->ap_next, cp = *cpp);

				if (cp) {
					/* zap cp, and join cpp to cp->ap_next */
					*cpp = cp->ap_next;
					constraint_free( cp, 1 );
				}
				on->on_bi.bi_private = cn;
			}
			break;

		default:
			abort();
			break;
		}
		break;
	case SLAP_CONFIG_ADD:
	case LDAP_MOD_ADD:
		switch (c->type) {
		case CONSTRAINT_ATTRIBUTE: {
			int j;
			char **attrs = ldap_str2charray( c->argv[1], "," );

			for ( j = 0; attrs[j]; j++)
				/* just count */ ;
			ap.ap = ch_calloc( sizeof(AttributeDescription*), j + 1 );
			for ( j = 0; attrs[j]; j++) {
				if ( slap_str2ad( attrs[j], &ap.ap[j], &text ) ) {
					snprintf( c->cr_msg, sizeof( c->cr_msg ),
						"%s <%s>: %s\n", c->argv[0], attrs[j], text );
					rc = ARG_BAD_CONF;
					goto done;
				}
			}

			if ( strcasecmp( c->argv[2], REGEX_STR ) == 0) {
				int err;
			
				ap.re = ch_malloc( sizeof(regex_t) );
				if ((err = regcomp( ap.re,
					c->argv[3], REG_EXTENDED )) != 0) {
					char errmsg[1024];
							
					regerror( err, ap.re, errmsg, sizeof(errmsg) );
					ch_free(ap.re);
					snprintf( c->cr_msg, sizeof( c->cr_msg ),
						"%s %s: Illegal regular expression \"%s\": Error %s",
						c->argv[0], c->argv[1], c->argv[3], errmsg);
					ap.re = NULL;
					rc = ARG_BAD_CONF;
					goto done;
				}
				ber_str2bv( c->argv[3], 0, 1, &ap.val );
			} else if ( strcasecmp( c->argv[2], SIZE_STR ) == 0 ) {
				size_t size;

				if ( ( size = atoi(c->argv[3]) ) != 0 )
					ap.size = size;	
			} else if ( strcasecmp( c->argv[2], COUNT_STR ) == 0 ) {
				size_t count;

				if ( ( count = atoi(c->argv[3]) ) != 0 )
					ap.count = count;	
			} else if ( strcasecmp( c->argv[2], URI_STR ) == 0 ) {
				int err;
			
				err = ldap_url_parse(c->argv[3], &ap.lud);
				if ( err != LDAP_URL_SUCCESS ) {
					snprintf( c->cr_msg, sizeof( c->cr_msg ),
						"%s %s: Invalid URI \"%s\"",
						c->argv[0], c->argv[1], c->argv[3]);
					rc = ARG_BAD_CONF;
					goto done;
				}

				if (ap.lud->lud_host != NULL) {
					snprintf( c->cr_msg, sizeof( c->cr_msg ),
						"%s %s: unsupported hostname in URI \"%s\"",
						c->argv[0], c->argv[1], c->argv[3]);
					ldap_free_urldesc(ap.lud);
					rc = ARG_BAD_CONF;
					goto done;
				}

				for ( i=0; ap.lud->lud_attrs[i]; i++);
				/* FIXME: This is worthless without at least one attr */
				if ( i ) {
					ap.attrs = ch_malloc( (i+1)*sizeof(AttributeDescription *));
					for ( i=0; ap.lud->lud_attrs[i]; i++) {
						ap.attrs[i] = NULL;
						if ( slap_str2ad( ap.lud->lud_attrs[i], &ap.attrs[i], &text ) ) {
							ch_free( ap.attrs );
							snprintf( c->cr_msg, sizeof( c->cr_msg ),
								"%s <%s>: %s\n", c->argv[0], ap.lud->lud_attrs[i], text );
							rc = ARG_BAD_CONF;
							goto done;
						}
					}
					ap.attrs[i] = NULL;
				}

				if (ap.lud->lud_dn == NULL) {
					ap.lud->lud_dn = ch_strdup("");
				} else {
					struct berval dn, ndn;

					ber_str2bv( ap.lud->lud_dn, 0, 0, &dn );
					if (dnNormalize( 0, NULL, NULL, &dn, &ndn, NULL ) ) {
						/* cleanup */
						snprintf( c->cr_msg, sizeof( c->cr_msg ),
							"%s %s: URI %s DN normalization failed",
							c->argv[0], c->argv[1], c->argv[3] );
						Debug( LDAP_DEBUG_CONFIG|LDAP_DEBUG_NONE,
							   "%s: %s\n", c->log, c->cr_msg, 0 );
						rc = ARG_BAD_CONF;
						goto done;
					}
					ldap_memfree( ap.lud->lud_dn );
					ap.lud->lud_dn = ndn.bv_val;
				}

				if (ap.lud->lud_filter == NULL) {
					ap.lud->lud_filter = ch_strdup("objectClass=*");
				} else if ( ap.lud->lud_filter[0] == '(' ) {
					ber_len_t len = strlen( ap.lud->lud_filter );
					if ( ap.lud->lud_filter[len - 1] != ')' ) {
						snprintf( c->cr_msg, sizeof( c->cr_msg ),
							"%s %s: invalid URI filter: %s",
							c->argv[0], c->argv[1], ap.lud->lud_filter );
						rc = ARG_BAD_CONF;
						goto done;
					}
					AC_MEMCPY( &ap.lud->lud_filter[0], &ap.lud->lud_filter[1], len - 2 );
					ap.lud->lud_filter[len - 2] = '\0';
				}

				ber_str2bv( c->argv[3], 0, 1, &ap.val );

			} else if ( strcasecmp( c->argv[2], SET_STR ) == 0 ) {
				ap.set = 1;
				ber_str2bv( c->argv[3], 0, 1, &ap.val );

			} else {
				snprintf( c->cr_msg, sizeof( c->cr_msg ),
					"%s %s: Unknown constraint type: %s",
					c->argv[0], c->argv[1], c->argv[2] );
				rc = ARG_BAD_CONF;
				goto done;
			}

			if ( c->argc > 4 ) {
				int argidx;

				for ( argidx = 4; argidx < c->argc; argidx++ ) {
					if ( strncasecmp( c->argv[argidx], "restrict=", STRLENOF("restrict=") ) == 0 ) {
						int err;
						char *arg = c->argv[argidx] + STRLENOF("restrict=");

						err = ldap_url_parse(arg, &ap.restrict_lud);
						if ( err != LDAP_URL_SUCCESS ) {
							snprintf( c->cr_msg, sizeof( c->cr_msg ),
								"%s %s: Invalid restrict URI \"%s\"",
								c->argv[0], c->argv[1], arg);
							rc = ARG_BAD_CONF;
							goto done;
						}

						if (ap.restrict_lud->lud_host != NULL) {
							snprintf( c->cr_msg, sizeof( c->cr_msg ),
								"%s %s: unsupported hostname in restrict URI \"%s\"",
								c->argv[0], c->argv[1], arg);
							rc = ARG_BAD_CONF;
							goto done;
						}

						if ( ap.restrict_lud->lud_attrs != NULL ) {
							if ( ap.restrict_lud->lud_attrs[0] != '\0' ) {
								snprintf( c->cr_msg, sizeof( c->cr_msg ),
									"%s %s: attrs not allowed in restrict URI %s\n",
									c->argv[0], c->argv[1], arg);
								rc = ARG_BAD_CONF;
								goto done;
							}
							ldap_memvfree((void *)ap.restrict_lud->lud_attrs);
							ap.restrict_lud->lud_attrs = NULL;
						}

						if (ap.restrict_lud->lud_dn != NULL) {
							if (ap.restrict_lud->lud_dn[0] == '\0') {
								ldap_memfree(ap.restrict_lud->lud_dn);
								ap.restrict_lud->lud_dn = NULL;

							} else {
								struct berval dn, ndn;
								int j;

								ber_str2bv(ap.restrict_lud->lud_dn, 0, 0, &dn);
								if (dnNormalize(0, NULL, NULL, &dn, &ndn, NULL)) {
									/* cleanup */
									snprintf( c->cr_msg, sizeof( c->cr_msg ),
										"%s %s: restrict URI %s DN normalization failed",
										c->argv[0], c->argv[1], arg );
									rc = ARG_BAD_CONF;
									goto done;
								}

								assert(c->be != NULL);
								if (c->be->be_nsuffix == NULL) {
									snprintf( c->cr_msg, sizeof( c->cr_msg ),
										"%s %s: restrict URI requires suffix",
										c->argv[0], c->argv[1] );
									rc = ARG_BAD_CONF;
									goto done;
								}

								for ( j = 0; !BER_BVISNULL(&c->be->be_nsuffix[j]); j++) {
									if (dnIsSuffix(&ndn, &c->be->be_nsuffix[j])) break;
								}

								if (BER_BVISNULL(&c->be->be_nsuffix[j])) {
									/* error */
									snprintf( c->cr_msg, sizeof( c->cr_msg ),
										"%s %s: restrict URI DN %s not within database naming context(s)",
										c->argv[0], c->argv[1], dn.bv_val );
									rc = ARG_BAD_CONF;
									goto done;
								}

								ap.restrict_ndn = ndn;
							}
						}

						if (ap.restrict_lud->lud_filter != NULL) {
							ap.restrict_filter = str2filter(ap.restrict_lud->lud_filter);
							if (ap.restrict_filter == NULL) {
								/* error */
								snprintf( c->cr_msg, sizeof( c->cr_msg ),
									"%s %s: restrict URI filter %s invalid",
									c->argv[0], c->argv[1], ap.restrict_lud->lud_filter );
								rc = ARG_BAD_CONF;
								goto done;
							}
						}

						ber_str2bv(c->argv[argidx], 0, 1, &ap.restrict_val);

					} else {
						/* cleanup */
						snprintf( c->cr_msg, sizeof( c->cr_msg ),
							"%s %s: unrecognized arg #%d (%s)",
							c->argv[0], c->argv[1], argidx, c->argv[argidx] );
						rc = ARG_BAD_CONF;
						goto done;
					}
				}
			}

done:;
			if ( rc == LDAP_SUCCESS ) {
				constraint *a2 = ch_calloc( sizeof(constraint), 1 );
				a2->ap_next = on->on_bi.bi_private;
				a2->ap = ap.ap;
				a2->re = ap.re;
				a2->val = ap.val;
				a2->lud = ap.lud;
				a2->set = ap.set;
				a2->size = ap.size;
				a2->count = ap.count;
				if ( a2->lud ) {
					ber_str2bv(a2->lud->lud_dn, 0, 0, &a2->dn);
					ber_str2bv(a2->lud->lud_filter, 0, 0, &a2->filter);
				}
				a2->attrs = ap.attrs;
				a2->restrict_lud = ap.restrict_lud;
				a2->restrict_ndn = ap.restrict_ndn;
				a2->restrict_filter = ap.restrict_filter;
				a2->restrict_val = ap.restrict_val;
				on->on_bi.bi_private = a2;

			} else {
				Debug( LDAP_DEBUG_CONFIG|LDAP_DEBUG_NONE,
					   "%s: %s\n", c->log, c->cr_msg, 0 );
				constraint_free( &ap, 0 );
			}

			ldap_memvfree((void**)attrs);
			} break;
		default:
			abort();
			break;
		}
		break;
	default:
		abort();
	}

	return rc;
}
Exemple #12
0
static void *
slapd_rw_config( const char *fname, int lineno, int argc, char **argv )
{
	slapd_map_data *ret = NULL;
	LDAPURLDesc *lud = NULL;
	char *uri;
	AttributeDescription *ad = NULL;
	int rc, flen = 0;
	struct berval dn, ndn;

	if ( argc != 1 ) {
		Debug( LDAP_DEBUG_ANY,
			"[%s:%d] slapd map needs URI\n",
			fname, lineno, 0 );
        return NULL;
	}

	uri = argv[0];
	if ( strncasecmp( uri, "uri=", STRLENOF( "uri=" ) ) == 0 ) {
		uri += STRLENOF( "uri=" );
	}

	if ( ldap_url_parse( uri, &lud ) != LDAP_URL_SUCCESS ) {
		Debug( LDAP_DEBUG_ANY,
			"[%s:%d] illegal URI '%s'\n",
			fname, lineno, uri );
        return NULL;
	}

	if ( strcasecmp( lud->lud_scheme, "ldap" )) {
		Debug( LDAP_DEBUG_ANY,
			"[%s:%d] illegal URI scheme '%s'\n",
			fname, lineno, lud->lud_scheme );
		goto done;
	}

	if (( lud->lud_host && lud->lud_host[0] ) || lud->lud_exts
		|| !lud->lud_dn ) {
		Debug( LDAP_DEBUG_ANY,
			"[%s:%d] illegal URI '%s'\n",
			fname, lineno, uri );
		goto done;
	}

	if ( lud->lud_attrs ) {
		if ( lud->lud_attrs[1] ) {
			Debug( LDAP_DEBUG_ANY,
				"[%s:%d] only one attribute allowed in URI\n",
				fname, lineno, 0 );
			goto done;
		}
		if ( strcasecmp( lud->lud_attrs[0], "dn" ) &&
			strcasecmp( lud->lud_attrs[0], "entryDN" )) {
			const char *text;
			rc = slap_str2ad( lud->lud_attrs[0], &ad, &text );
			if ( rc )
				goto done;
		}
	}
	ber_str2bv( lud->lud_dn, 0, 0, &dn );
	if ( dnNormalize( 0, NULL, NULL, &dn, &ndn, NULL ))
		goto done;

	if ( lud->lud_filter ) {
		flen = strlen( lud->lud_filter ) + 1;
	}
	ret = ch_malloc( sizeof( slapd_map_data ) + flen );
	ret->base = ndn;
	if ( flen ) {
		ret->filter.bv_val = (char *)(ret+1);
		ret->filter.bv_len = flen - 1;
		strcpy( ret->filter.bv_val, lud->lud_filter );
	} else {
		BER_BVZERO( &ret->filter );
	}
	ret->scope = lud->lud_scope;
	if ( ad ) {
		ret->attrs[0].an_name = ad->ad_cname;
	} else {
		BER_BVZERO( &ret->attrs[0].an_name );
	}
	ret->attrs[0].an_desc = ad;
	BER_BVZERO( &ret->attrs[1].an_name );
done:
	ldap_free_urldesc( lud );
	return ret;
}
Exemple #13
0
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;
}
Exemple #14
0
static int
nss_cf_gen(ConfigArgs *c)
{
	slap_overinst *on = (slap_overinst *)c->bi;
	nssov_info *ni = on->on_bi.bi_private;
	nssov_mapinfo *mi;
	int i, j, rc = 0;
	slap_mask_t m;

	if ( c->op == SLAP_CONFIG_EMIT ) {
		switch(c->type) {
		case NSS_SSD:
			rc = 1;
			for (i=NM_alias;i<NM_NONE;i++) {
				struct berval scope;
				struct berval ssd;
				struct berval base;

				mi = &ni->ni_maps[i];

				/* ignore all-default services */
				if ( mi->mi_scope == LDAP_SCOPE_DEFAULT &&
					bvmatch( &mi->mi_filter, &mi->mi_filter0 ) &&
					BER_BVISNULL( &mi->mi_base ))
					continue;

				if ( BER_BVISNULL( &mi->mi_base ))
					base = ni->ni_db->be_nsuffix[0];
				else
					base = mi->mi_base;
				ldap_pvt_scope2bv(mi->mi_scope == LDAP_SCOPE_DEFAULT ?
					LDAP_SCOPE_SUBTREE : mi->mi_scope, &scope);
				ssd.bv_len = STRLENOF(" ldap:///???") + nss_svcs[i].word.bv_len +
					base.bv_len + scope.bv_len + mi->mi_filter.bv_len;
				ssd.bv_val = ch_malloc( ssd.bv_len + 1 );
				sprintf(ssd.bv_val, "%s ldap:///%s??%s?%s", nss_svcs[i].word.bv_val,
					base.bv_val, scope.bv_val, mi->mi_filter.bv_val );
				ber_bvarray_add( &c->rvalue_vals, &ssd );
				rc = 0;
			}
			break;
		case NSS_MAP:
			rc = 1;
			for (i=NM_alias;i<NM_NONE;i++) {

				mi = &ni->ni_maps[i];
				for (j=0;!BER_BVISNULL(&mi->mi_attrkeys[j]);j++) {
					if ( ber_bvstrcasecmp(&mi->mi_attrkeys[j],
						&mi->mi_attrs[j].an_name)) {
						struct berval map;

						map.bv_len = nss_svcs[i].word.bv_len +
							mi->mi_attrkeys[j].bv_len +
							mi->mi_attrs[j].an_desc->ad_cname.bv_len + 2;
						map.bv_val = ch_malloc(map.bv_len + 1);
						sprintf(map.bv_val, "%s %s %s", nss_svcs[i].word.bv_val,
							mi->mi_attrkeys[j].bv_val, mi->mi_attrs[j].an_desc->ad_cname.bv_val );
						ber_bvarray_add( &c->rvalue_vals, &map );
						rc = 0;
					}
				}
			}
			break;
		case NSS_PAM:
			rc = mask_to_verbs( pam_opts, ni->ni_pam_opts, &c->rvalue_vals );
			break;
		case NSS_PAMGROUP:
			if (!BER_BVISEMPTY( &ni->ni_pam_group_dn )) {
				value_add_one( &c->rvalue_vals, &ni->ni_pam_group_dn );
				value_add_one( &c->rvalue_nvals, &ni->ni_pam_group_dn );
			} else {
				rc = 1;
			}
			break;
		case NSS_PAMSESS:
			if (ni->ni_pam_sessions) {
				ber_bvarray_dup_x( &c->rvalue_vals, ni->ni_pam_sessions, NULL );
			} else {
				rc = 1;
			}
			break;
		}
		return rc;
	} else if ( c->op == LDAP_MOD_DELETE ) {
		/* FIXME */
		return 1;
	}
	switch( c->type ) {
	case NSS_SSD: {
		LDAPURLDesc *lud;

		i = verb_to_mask(c->argv[1], nss_svcs);
		if ( i == NM_NONE )
			return 1;

		mi = &ni->ni_maps[i];
		rc = ldap_url_parse(c->argv[2], &lud);
		if ( rc )
			return 1;
		do {
			struct berval base;
			/* Must be LDAP scheme */
			if (strcasecmp(lud->lud_scheme,"ldap")) {
				rc = 1;
				break;
			}
			/* Host part, attrs, and extensions must be empty */
			if (( lud->lud_host && *lud->lud_host ) ||
				lud->lud_attrs || lud->lud_exts ) {
				rc = 1;
				break;
			}
			ber_str2bv( lud->lud_dn,0,0,&base);
			rc = dnNormalize( 0,NULL,NULL,&base,&mi->mi_base,NULL);
			if ( rc )
				break;
			if ( lud->lud_filter ) {
				/* steal this */
				ber_str2bv( lud->lud_filter,0,0,&mi->mi_filter);
				lud->lud_filter = NULL;
			}
			mi->mi_scope = lud->lud_scope;
		} while(0);
		ldap_free_urldesc( lud );
		}
		break;
	case NSS_MAP:
		i = verb_to_mask(c->argv[1], nss_svcs);
		if ( i == NM_NONE )
			return 1;
		rc = 1;
		mi = &ni->ni_maps[i];
		for (j=0; !BER_BVISNULL(&mi->mi_attrkeys[j]); j++) {
			if (!strcasecmp(c->argv[2],mi->mi_attrkeys[j].bv_val)) {
				AttributeDescription *ad = NULL;
				const char *text;
				rc = slap_str2ad( c->argv[3], &ad, &text);
				if ( rc == 0 ) {
					mi->mi_attrs[j].an_desc = ad;
					mi->mi_attrs[j].an_name = ad->ad_cname;
				}
				break;
			}
		}
		break;
	case NSS_PAM:
		m = ni->ni_pam_opts;
		i = verbs_to_mask(c->argc, c->argv, pam_opts, &m);
		if (i == 0) {
			ni->ni_pam_opts = m;
			if ((m & NI_PAM_USERHOST) && !nssov_pam_host_ad) {
				const char *text;
				i = slap_str2ad("host", &nssov_pam_host_ad, &text);
				if (i != LDAP_SUCCESS) {
					snprintf(c->cr_msg, sizeof(c->cr_msg),
						"nssov: host attr unknown: %s", text);
					Debug(LDAP_DEBUG_ANY,"%s\n",c->cr_msg,0,0);
					rc = 1;
					break;
				}
			}
			if ((m & (NI_PAM_USERSVC|NI_PAM_HOSTSVC)) && !nssov_pam_svc_ad) {
				const char *text;
				i = slap_str2ad("authorizedService", &nssov_pam_svc_ad, &text);
				if (i != LDAP_SUCCESS) {
					snprintf(c->cr_msg, sizeof(c->cr_msg),
						"nssov: authorizedService attr unknown: %s", text);
					Debug(LDAP_DEBUG_ANY,"%s\n",c->cr_msg,0,0);
					rc = 1;
					break;
				}
			}
		} else {
			rc = 1;
		}
		break;
	case NSS_PAMGROUP:
		ni->ni_pam_group_dn = c->value_ndn;
		ch_free( c->value_dn.bv_val );
		break;
	case NSS_PAMSESS:
		ber_bvarray_add( &ni->ni_pam_sessions, &c->value_bv );
		break;
	}
	return rc;
}
Exemple #15
0
static int
dl_cfgen( ConfigArgs *c )
{
	slap_overinst	*on = (slap_overinst *)c->bi;
	dynlist_info_t	*dli = (dynlist_info_t *)on->on_bi.bi_private;

	int		rc = 0, i;

	if ( c->op == SLAP_CONFIG_EMIT ) {
		switch( c->type ) {
		case DL_ATTRSET:
			for ( i = 0; dli; i++, dli = dli->dli_next ) {
				struct berval	bv;
				char		*ptr = c->cr_msg;
				dynlist_map_t	*dlm;

				assert( dli->dli_oc != NULL );
				assert( dli->dli_ad != NULL );

				/* FIXME: check buffer overflow! */
				ptr += snprintf( c->cr_msg, sizeof( c->cr_msg ),
					SLAP_X_ORDERED_FMT "%s", i,
					dli->dli_oc->soc_cname.bv_val );

				if ( !BER_BVISNULL( &dli->dli_uri ) ) {
					*ptr++ = ' ';
					*ptr++ = '"';
					ptr = lutil_strncopy( ptr, dli->dli_uri.bv_val,
						dli->dli_uri.bv_len );
					*ptr++ = '"';
				}

				*ptr++ = ' ';
				ptr = lutil_strncopy( ptr, dli->dli_ad->ad_cname.bv_val,
					dli->dli_ad->ad_cname.bv_len );

				for ( dlm = dli->dli_dlm; dlm; dlm = dlm->dlm_next ) {
					ptr[ 0 ] = ' ';
					ptr++;
					if ( dlm->dlm_mapped_ad ) {
						ptr = lutil_strcopy( ptr, dlm->dlm_mapped_ad->ad_cname.bv_val );
						ptr[ 0 ] = ':';
						ptr++;
					}
						
					ptr = lutil_strcopy( ptr, dlm->dlm_member_ad->ad_cname.bv_val );
				}

				bv.bv_val = c->cr_msg;
				bv.bv_len = ptr - bv.bv_val;
				value_add_one( &c->rvalue_vals, &bv );
			}
			break;

		case DL_ATTRPAIR_COMPAT:
		case DL_ATTRPAIR:
			rc = 1;
			break;

		default:
			rc = 1;
			break;
		}

		return rc;

	} else if ( c->op == LDAP_MOD_DELETE ) {
		switch( c->type ) {
		case DL_ATTRSET:
			if ( c->valx < 0 ) {
				dynlist_info_t	*dli_next;

				for ( dli_next = dli; dli_next; dli = dli_next ) {
					dynlist_map_t *dlm = dli->dli_dlm;
					dynlist_map_t *dlm_next;

					dli_next = dli->dli_next;

					if ( !BER_BVISNULL( &dli->dli_uri ) ) {
						ch_free( dli->dli_uri.bv_val );
					}

					if ( dli->dli_lud != NULL ) {
						ldap_free_urldesc( dli->dli_lud );
					}

					if ( !BER_BVISNULL( &dli->dli_uri_nbase ) ) {
						ber_memfree( dli->dli_uri_nbase.bv_val );
					}

					if ( dli->dli_uri_filter != NULL ) {
						filter_free( dli->dli_uri_filter );
					}

					ch_free( dli->dli_default_filter.bv_val );

					while ( dlm != NULL ) {
						dlm_next = dlm->dlm_next;
						ch_free( dlm );
						dlm = dlm_next;
					}
					ch_free( dli );
				}

				on->on_bi.bi_private = NULL;

			} else {
				dynlist_info_t	**dlip;
				dynlist_map_t *dlm;
				dynlist_map_t *dlm_next;

				for ( i = 0, dlip = (dynlist_info_t **)&on->on_bi.bi_private;
					i < c->valx; i++ )
				{
					if ( *dlip == NULL ) {
						return 1;
					}
					dlip = &(*dlip)->dli_next;
				}

				dli = *dlip;
				*dlip = dli->dli_next;

				if ( !BER_BVISNULL( &dli->dli_uri ) ) {
					ch_free( dli->dli_uri.bv_val );
				}

				if ( dli->dli_lud != NULL ) {
					ldap_free_urldesc( dli->dli_lud );
				}

				if ( !BER_BVISNULL( &dli->dli_uri_nbase ) ) {
					ber_memfree( dli->dli_uri_nbase.bv_val );
				}

				if ( dli->dli_uri_filter != NULL ) {
					filter_free( dli->dli_uri_filter );
				}

				ch_free( dli->dli_default_filter.bv_val );

				dlm = dli->dli_dlm;
				while ( dlm != NULL ) {
					dlm_next = dlm->dlm_next;
					ch_free( dlm );
					dlm = dlm_next;
				}
				ch_free( dli );

				dli = (dynlist_info_t *)on->on_bi.bi_private;
			}
			break;

		case DL_ATTRPAIR_COMPAT:
		case DL_ATTRPAIR:
			rc = 1;
			break;

		default:
			rc = 1;
			break;
		}

		return rc;
	}

	switch( c->type ) {
	case DL_ATTRSET: {
		dynlist_info_t		**dlip,
					*dli_next = NULL;
		ObjectClass		*oc = NULL;
		AttributeDescription	*ad = NULL;
		int			attridx = 2;
		LDAPURLDesc		*lud = NULL;
		struct berval		nbase = BER_BVNULL;
		Filter			*filter = NULL;
		struct berval		uri = BER_BVNULL;
		dynlist_map_t           *dlm = NULL, *dlml = NULL;
		const char		*text;

		oc = oc_find( c->argv[ 1 ] );
		if ( oc == NULL ) {
			snprintf( c->cr_msg, sizeof( c->cr_msg ), DYNLIST_USAGE
				"unable to find ObjectClass \"%s\"",
				c->argv[ 1 ] );
			Debug( LDAP_DEBUG_ANY, "%s: %s.\n",
				c->log, c->cr_msg, 0 );
			return 1;
		}

		if ( strncasecmp( c->argv[ attridx ], "ldap://", STRLENOF("ldap://") ) == 0 ) {
			if ( ldap_url_parse( c->argv[ attridx ], &lud ) != LDAP_URL_SUCCESS ) {
				snprintf( c->cr_msg, sizeof( c->cr_msg ), DYNLIST_USAGE
					"unable to parse URI \"%s\"",
					c->argv[ attridx ] );
				rc = 1;
				goto done_uri;
			}

			if ( lud->lud_host != NULL ) {
				if ( lud->lud_host[0] == '\0' ) {
					ch_free( lud->lud_host );
					lud->lud_host = NULL;

				} else {
					snprintf( c->cr_msg, sizeof( c->cr_msg ), DYNLIST_USAGE
						"host not allowed in URI \"%s\"",
						c->argv[ attridx ] );
					rc = 1;
					goto done_uri;
				}
			}

			if ( lud->lud_attrs != NULL ) {
				snprintf( c->cr_msg, sizeof( c->cr_msg ), DYNLIST_USAGE
					"attrs not allowed in URI \"%s\"",
					c->argv[ attridx ] );
				rc = 1;
				goto done_uri;
			}

			if ( lud->lud_exts != NULL ) {
				snprintf( c->cr_msg, sizeof( c->cr_msg ), DYNLIST_USAGE
					"extensions not allowed in URI \"%s\"",
					c->argv[ attridx ] );
				rc = 1;
				goto done_uri;
			}

			if ( lud->lud_dn != NULL && lud->lud_dn[ 0 ] != '\0' ) {
				struct berval dn;
				ber_str2bv( lud->lud_dn, 0, 0, &dn );
				rc = dnNormalize( 0, NULL, NULL, &dn, &nbase, NULL );
				if ( rc != LDAP_SUCCESS ) {
					snprintf( c->cr_msg, sizeof( c->cr_msg ), DYNLIST_USAGE
						"DN normalization failed in URI \"%s\"",
						c->argv[ attridx ] );
					goto done_uri;
				}
			}

			if ( lud->lud_filter != NULL && lud->lud_filter[ 0 ] != '\0' ) {
				filter = str2filter( lud->lud_filter );
				if ( filter == NULL ) {
					snprintf( c->cr_msg, sizeof( c->cr_msg ), DYNLIST_USAGE
						"filter parsing failed in URI \"%s\"",
						c->argv[ attridx ] );
					rc = 1;
					goto done_uri;
				}
			}

			ber_str2bv( c->argv[ attridx ], 0, 1, &uri );

done_uri:;
			if ( rc ) {
				if ( lud ) {
					ldap_free_urldesc( lud );
				}

				if ( !BER_BVISNULL( &nbase ) ) {
					ber_memfree( nbase.bv_val );
				}

				if ( filter != NULL ) {
					filter_free( filter );
				}

				while ( dlm != NULL ) {
					dlml = dlm;
					dlm = dlm->dlm_next;
					ch_free( dlml );
				}

				Debug( LDAP_DEBUG_ANY, "%s: %s.\n",
					c->log, c->cr_msg, 0 );

				return rc;
			}

			attridx++;
		}

		rc = slap_str2ad( c->argv[ attridx ], &ad, &text );
		if ( rc != LDAP_SUCCESS ) {
			snprintf( c->cr_msg, sizeof( c->cr_msg ), DYNLIST_USAGE
				"unable to find AttributeDescription \"%s\"",
				c->argv[ attridx ] );
			Debug( LDAP_DEBUG_ANY, "%s: %s.\n",
				c->log, c->cr_msg, 0 );
			rc = 1;
			goto done_uri;
		}

		if ( !is_at_subtype( ad->ad_type, slap_schema.si_ad_labeledURI->ad_type ) ) {
			snprintf( c->cr_msg, sizeof( c->cr_msg ), DYNLIST_USAGE
				"AttributeDescription \"%s\" "
				"must be a subtype of \"labeledURI\"",
				c->argv[ attridx ] );
			Debug( LDAP_DEBUG_ANY, "%s: %s.\n",
				c->log, c->cr_msg, 0 );
			rc = 1;
			goto done_uri;
		}

		attridx++;

		for ( i = attridx; i < c->argc; i++ ) {
			char *arg; 
			char *cp;
			AttributeDescription *member_ad = NULL;
			AttributeDescription *mapped_ad = NULL;
			dynlist_map_t *dlmp;


			/*
			 * If no mapped attribute is given, dn is used 
			 * for backward compatibility.
			 */
			arg = c->argv[i];
			if ( ( cp = strchr( arg, ':' ) ) != NULL ) {
				struct berval bv;
				ber_str2bv( arg, cp - arg, 0, &bv );
				rc = slap_bv2ad( &bv, &mapped_ad, &text );
				if ( rc != LDAP_SUCCESS ) {
					snprintf( c->cr_msg, sizeof( c->cr_msg ),
						DYNLIST_USAGE
						"unable to find mapped AttributeDescription #%d \"%s\"\n",
						i - 3, c->argv[ i ] );
					Debug( LDAP_DEBUG_ANY, "%s: %s.\n",
						c->log, c->cr_msg, 0 );
					rc = 1;
					goto done_uri;
				}
				arg = cp + 1;
			}

			rc = slap_str2ad( arg, &member_ad, &text );
			if ( rc != LDAP_SUCCESS ) {
				snprintf( c->cr_msg, sizeof( c->cr_msg ),
					DYNLIST_USAGE
					"unable to find AttributeDescription #%d \"%s\"\n",
					i - 3, c->argv[ i ] );
				Debug( LDAP_DEBUG_ANY, "%s: %s.\n",
					c->log, c->cr_msg, 0 );
				rc = 1;
				goto done_uri;
			}

			dlmp = (dynlist_map_t *)ch_calloc( 1, sizeof( dynlist_map_t ) );
			if ( dlm == NULL ) {
				dlm = dlmp;
			}
			dlmp->dlm_member_ad = member_ad;
			dlmp->dlm_mapped_ad = mapped_ad;
			dlmp->dlm_next = NULL;
		
			if ( dlml != NULL ) 
				dlml->dlm_next = dlmp;
			dlml = dlmp;
		}

		if ( c->valx > 0 ) {
			int	i;

			for ( i = 0, dlip = (dynlist_info_t **)&on->on_bi.bi_private;
				i < c->valx; i++ )
			{
				if ( *dlip == NULL ) {
					snprintf( c->cr_msg, sizeof( c->cr_msg ),
						DYNLIST_USAGE
						"invalid index {%d}\n",
						c->valx );
					Debug( LDAP_DEBUG_ANY, "%s: %s.\n",
						c->log, c->cr_msg, 0 );
					rc = 1;
					goto done_uri;
				}
				dlip = &(*dlip)->dli_next;
			}
			dli_next = *dlip;

		} else {
			for ( dlip = (dynlist_info_t **)&on->on_bi.bi_private;
				*dlip; dlip = &(*dlip)->dli_next )
				/* goto last */;
		}

		*dlip = (dynlist_info_t *)ch_calloc( 1, sizeof( dynlist_info_t ) );

		(*dlip)->dli_oc = oc;
		(*dlip)->dli_ad = ad;
		(*dlip)->dli_dlm = dlm;
		(*dlip)->dli_next = dli_next;

		(*dlip)->dli_lud = lud;
		(*dlip)->dli_uri_nbase = nbase;
		(*dlip)->dli_uri_filter = filter;
		(*dlip)->dli_uri = uri;

		rc = dynlist_build_def_filter( *dlip );

		} break;

	case DL_ATTRPAIR_COMPAT:
		snprintf( c->cr_msg, sizeof( c->cr_msg ),
			"warning: \"attrpair\" only supported for limited "
			"backward compatibility with overlay \"dyngroup\"" );
		Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg, 0 );
		/* fallthru */

	case DL_ATTRPAIR: {
		dynlist_info_t		**dlip;
		ObjectClass		*oc = NULL;
		AttributeDescription	*ad = NULL,
					*member_ad = NULL;
		const char		*text;

		oc = oc_find( "groupOfURLs" );
		if ( oc == NULL ) {
			snprintf( c->cr_msg, sizeof( c->cr_msg ),
				"\"dynlist-attrpair <member-ad> <URL-ad>\": "
				"unable to find default ObjectClass \"groupOfURLs\"" );
			Debug( LDAP_DEBUG_ANY, "%s: %s.\n",
				c->log, c->cr_msg, 0 );
			return 1;
		}

		rc = slap_str2ad( c->argv[ 1 ], &member_ad, &text );
		if ( rc != LDAP_SUCCESS ) {
			snprintf( c->cr_msg, sizeof( c->cr_msg ),
				"\"dynlist-attrpair <member-ad> <URL-ad>\": "
				"unable to find AttributeDescription \"%s\"",
				c->argv[ 1 ] );
			Debug( LDAP_DEBUG_ANY, "%s: %s.\n",
				c->log, c->cr_msg, 0 );
			return 1;
		}

		rc = slap_str2ad( c->argv[ 2 ], &ad, &text );
		if ( rc != LDAP_SUCCESS ) {
			snprintf( c->cr_msg, sizeof( c->cr_msg ),
				"\"dynlist-attrpair <member-ad> <URL-ad>\": "
				"unable to find AttributeDescription \"%s\"\n",
				c->argv[ 2 ] );
			Debug( LDAP_DEBUG_ANY, "%s: %s.\n",
				c->log, c->cr_msg, 0 );
			return 1;
		}

		if ( !is_at_subtype( ad->ad_type, slap_schema.si_ad_labeledURI->ad_type ) ) {
			snprintf( c->cr_msg, sizeof( c->cr_msg ),
				DYNLIST_USAGE
				"AttributeDescription \"%s\" "
				"must be a subtype of \"labeledURI\"",
				c->argv[ 2 ] );
			Debug( LDAP_DEBUG_ANY, "%s: %s.\n",
				c->log, c->cr_msg, 0 );
			return 1;
		}

		for ( dlip = (dynlist_info_t **)&on->on_bi.bi_private;
			*dlip; dlip = &(*dlip)->dli_next )
		{
			/* 
			 * The same URL attribute / member attribute pair
			 * cannot be repeated, but we enforce this only 
			 * when the member attribute is unique. Performing
			 * the check for multiple values would require
			 * sorting and comparing the lists, which is left
			 * as a future improvement
			 */
			if ( (*dlip)->dli_ad == ad &&
			     (*dlip)->dli_dlm->dlm_next == NULL &&
			     member_ad == (*dlip)->dli_dlm->dlm_member_ad ) {
				snprintf( c->cr_msg, sizeof( c->cr_msg ),
					"\"dynlist-attrpair <member-ad> <URL-ad>\": "
					"URL attributeDescription \"%s\" already mapped.\n",
					ad->ad_cname.bv_val );
				Debug( LDAP_DEBUG_ANY, "%s: %s.\n",
					c->log, c->cr_msg, 0 );
#if 0
				/* make it a warning... */
				return 1;
#endif
			}
		}

		*dlip = (dynlist_info_t *)ch_calloc( 1, sizeof( dynlist_info_t ) );

		(*dlip)->dli_oc = oc;
		(*dlip)->dli_ad = ad;
		(*dlip)->dli_dlm = (dynlist_map_t *)ch_calloc( 1, sizeof( dynlist_map_t ) );
		(*dlip)->dli_dlm->dlm_member_ad = member_ad;
		(*dlip)->dli_dlm->dlm_mapped_ad = NULL;

		rc = dynlist_build_def_filter( *dlip );

		} break;

	default:
		rc = 1;
		break;
	}

	return rc;
}
static int
pg_dynacl_mask(
	void			*priv,
	Operation		*op,
	Entry			*target,
	AttributeDescription	*desc,
	struct berval		*val,
	int			nmatch,
	regmatch_t		*matches,
	slap_access_t		*grant,
	slap_access_t		*deny )
{
	pg_t		*pg = (pg_t *)priv;
	Entry		*group = NULL,
			*user = NULL;
	int		rc;
	Backend		*be = op->o_bd,
			*group_be = NULL,
			*user_be = NULL;
	struct berval	group_ndn;

	ACL_INVALIDATE( *deny );

	/* get user */
	if ( target && dn_match( &target->e_nname, &op->o_ndn ) ) {
		user = target;
		rc = LDAP_SUCCESS;

	} else {
		user_be = op->o_bd = select_backend( &op->o_ndn, 0 );
		if ( op->o_bd == NULL ) {
			op->o_bd = be;
			return 0;
		}
		rc = be_entry_get_rw( op, &op->o_ndn, pg_posixAccount, pg_uidNumber, 0, &user );
	}

	if ( rc != LDAP_SUCCESS || user == NULL ) {
		op->o_bd = be;
		return 0;
	}

	/* get target */
	if ( pg->pg_style == ACL_STYLE_EXPAND ) {
		char		buf[ 1024 ];
		struct berval	bv;
		AclRegexMatches amatches = { 0 };

		amatches.dn_count = nmatch;
		AC_MEMCPY( amatches.dn_data, matches, sizeof( amatches.dn_data ) );

		bv.bv_len = sizeof( buf ) - 1;
		bv.bv_val = buf;

		if ( acl_string_expand( &bv, &pg->pg_pat,
				&target->e_nname,
				NULL, &amatches ) )
		{
			goto cleanup;
		}

		if ( dnNormalize( 0, NULL, NULL, &bv, &group_ndn,
				op->o_tmpmemctx ) != LDAP_SUCCESS )
		{
			/* did not expand to a valid dn */
			goto cleanup;
		}
		
	} else {
		group_ndn = pg->pg_pat;
	}

	if ( target && dn_match( &target->e_nname, &group_ndn ) ) {
		group = target;
		rc = LDAP_SUCCESS;

	} else {
		group_be = op->o_bd = select_backend( &group_ndn, 0 );
		if ( op->o_bd == NULL ) {
			goto cleanup;
		}
		rc = be_entry_get_rw( op, &group_ndn, pg_posixGroup, pg_memberUid, 0, &group );
	}

	if ( group_ndn.bv_val != pg->pg_pat.bv_val ) {
		op->o_tmpfree( group_ndn.bv_val, op->o_tmpmemctx );
	}

	if ( rc == LDAP_SUCCESS && group != NULL ) {
		Attribute	*a_uid,
				*a_member;

		a_uid = attr_find( user->e_attrs, pg_uidNumber );
		if ( !a_uid || !BER_BVISNULL( &a_uid->a_nvals[ 1 ] ) ) {
			rc = LDAP_NO_SUCH_ATTRIBUTE;

		} else {
			a_member = attr_find( group->e_attrs, pg_memberUid );
			if ( !a_member ) {
				rc = LDAP_NO_SUCH_ATTRIBUTE;

			} else {
				rc = value_find_ex( pg_memberUid,
					SLAP_MR_ATTRIBUTE_VALUE_NORMALIZED_MATCH |
					SLAP_MR_ASSERTED_VALUE_NORMALIZED_MATCH,
					a_member->a_nvals, &a_uid->a_nvals[ 0 ],
					op->o_tmpmemctx );
			}
		}

	} else {
		rc = LDAP_NO_SUCH_OBJECT;
	}


	if ( rc == LDAP_SUCCESS ) {
		ACL_LVL_ASSIGN_WRITE( *grant );
	}

cleanup:;
	if ( group != NULL && group != target ) {
		op->o_bd = group_be;
		be_entry_release_r( op, group );
		op->o_bd = be;
	}

	if ( user != NULL && user != target ) {
		op->o_bd = user_be;
		be_entry_release_r( op, user );
		op->o_bd = be;
	}

	return 0;
}
static int
pg_dynacl_parse(
	const char	*fname,
	int 		lineno,
	const char	*opts,
	slap_style_t	style,
	const char	*pattern,
	void		**privp )
{
	pg_t		*pg;
	int		rc;
	const char	*text = NULL;
	struct berval	pat;

	ber_str2bv( pattern, 0, 0, &pat );

	pg = ch_calloc( 1, sizeof( pg_t ) );

	pg->pg_style = style;

	switch ( pg->pg_style ) {
	case ACL_STYLE_BASE:
		rc = dnNormalize( 0, NULL, NULL, &pat, &pg->pg_pat, NULL );
		if ( rc != LDAP_SUCCESS ) {
			fprintf( stderr, "%s line %d: posixGroup ACL: "
				"unable to normalize DN \"%s\".\n",
				fname, lineno, pattern );
			goto cleanup;
		}
		break;

	case ACL_STYLE_EXPAND:
		ber_dupbv( &pg->pg_pat, &pat );
		break;

	default:
		fprintf( stderr, "%s line %d: posixGroup ACL: "
			"unsupported style \"%s\".\n",
			fname, lineno, style_strings[ pg->pg_style ] );
		goto cleanup;
	}

	/* TODO: use opts to allow the use of different
	 * group objects and member attributes */
	if ( pg_posixGroup == NULL ) {
		pg_posixGroup = oc_find( "posixGroup" );
		if ( pg_posixGroup == NULL ) {
			fprintf( stderr, "%s line %d: posixGroup ACL: "
				"unable to lookup \"posixGroup\" "
				"objectClass.\n",
				fname, lineno );
			goto cleanup;
		}

		pg_posixAccount = oc_find( "posixAccount" );
		if ( pg_posixGroup == NULL ) {
			fprintf( stderr, "%s line %d: posixGroup ACL: "
				"unable to lookup \"posixAccount\" "
				"objectClass.\n",
				fname, lineno );
			goto cleanup;
		}

		rc = slap_str2ad( "memberUid", &pg_memberUid, &text );
		if ( rc != LDAP_SUCCESS ) {
			fprintf( stderr, "%s line %d: posixGroup ACL: "
				"unable to lookup \"memberUid\" "
				"attributeDescription (%d: %s).\n",
				fname, lineno, rc, text );
			goto cleanup;
		}

		rc = slap_str2ad( "uidNumber", &pg_uidNumber, &text );
		if ( rc != LDAP_SUCCESS ) {
			fprintf( stderr, "%s line %d: posixGroup ACL: "
				"unable to lookup \"uidNumber\" "
				"attributeDescription (%d: %s).\n",
				fname, lineno, rc, text );
			goto cleanup;
		}
	}

	*privp = (void *)pg;
	return 0;

cleanup:
	(void)pg_dynacl_destroy( (void *)pg );

	return 1;
}
Exemple #18
0
static int
limits_add(
	Backend 	        *be,
	unsigned		flags,
	const char		*pattern,
	ObjectClass		*group_oc,
	AttributeDescription	*group_ad,
	struct slap_limits_set	*limit
)
{
	int 			i;
	struct slap_limits	*lm;
	unsigned		type, style;
	
	assert( be != NULL );
	assert( limit != NULL );

	type = flags & SLAP_LIMITS_TYPE_MASK;
	style = flags & SLAP_LIMITS_MASK;

	switch ( style ) {
	case SLAP_LIMITS_ANONYMOUS:
	case SLAP_LIMITS_USERS:
	case SLAP_LIMITS_ANY:
		/* For these styles, type == 0 (SLAP_LIMITS_TYPE_SELF). */
		for ( i = 0; be->be_limits && be->be_limits[ i ]; i++ ) {
			if ( be->be_limits[ i ]->lm_flags == style ) {
				return( -1 );
			}
		}
		break;
	}


	lm = ( struct slap_limits * )ch_calloc( sizeof( struct slap_limits ), 1 );

	switch ( style ) {
	case SLAP_LIMITS_UNDEFINED:
		style = SLAP_LIMITS_EXACT;
		/* continue to next cases */
	case SLAP_LIMITS_EXACT:
	case SLAP_LIMITS_ONE:
	case SLAP_LIMITS_SUBTREE:
	case SLAP_LIMITS_CHILDREN:
		{
			int rc;
			struct berval bv;

			ber_str2bv( pattern, 0, 0, &bv );

			rc = dnNormalize( 0, NULL, NULL, &bv, &lm->lm_pat, NULL );
			if ( rc != LDAP_SUCCESS ) {
				ch_free( lm );
				return( -1 );
			}
		}
		break;
		
	case SLAP_LIMITS_REGEX:
		ber_str2bv( pattern, 0, 1, &lm->lm_pat );
		if ( regcomp( &lm->lm_regex, lm->lm_pat.bv_val, 
					REG_EXTENDED | REG_ICASE ) ) {
			free( lm->lm_pat.bv_val );
			ch_free( lm );
			return( -1 );
		}
		break;

	case SLAP_LIMITS_ANONYMOUS:
	case SLAP_LIMITS_USERS:
	case SLAP_LIMITS_ANY:
		BER_BVZERO( &lm->lm_pat );
		break;
	}

	switch ( type ) {
	case SLAP_LIMITS_TYPE_GROUP:
		assert( group_oc != NULL );
		assert( group_ad != NULL );
		lm->lm_group_oc = group_oc;
		lm->lm_group_ad = group_ad;
		break;
	}

	lm->lm_flags = style | type;
	lm->lm_limits = *limit;

	i = 0;
	if ( be->be_limits != NULL ) {
		for ( ; be->be_limits[i]; i++ );
	}

	be->be_limits = ( struct slap_limits ** )ch_realloc( be->be_limits,
			sizeof( struct slap_limits * ) * ( i + 2 ) );
	be->be_limits[i] = lm;
	be->be_limits[i+1] = NULL;
	
	return( 0 );
}
static int
collect_cf( ConfigArgs *c )
{
	slap_overinst *on = (slap_overinst *)c->bi;
	int rc = 1, idx;

	switch( c->op ) {
	case SLAP_CONFIG_EMIT:
		{
		collect_info *ci;
		for ( ci = on->on_bi.bi_private; ci; ci = ci->ci_next ) {
			struct berval bv;
			char *ptr;
			int len;

			/* calculate the length & malloc memory */
			bv.bv_len = ci->ci_dn.bv_len + STRLENOF("\"\" ");
			for (idx=0; idx<ci->ci_ad_num; idx++) {
				bv.bv_len += ci->ci_ad[idx]->ad_cname.bv_len;
				if (idx<(ci->ci_ad_num-1)) { 
					bv.bv_len++;
				}
			}
			bv.bv_val = ch_malloc( bv.bv_len + 1 );

			/* copy the value and update len */
			len = snprintf( bv.bv_val, bv.bv_len + 1, "\"%s\" ", 
				ci->ci_dn.bv_val);
			ptr = bv.bv_val + len;
			for (idx=0; idx<ci->ci_ad_num; idx++) {
				ptr = lutil_strncopy( ptr,
					ci->ci_ad[idx]->ad_cname.bv_val,
					ci->ci_ad[idx]->ad_cname.bv_len);
				if (idx<(ci->ci_ad_num-1)) {
					*ptr++ = ',';
				}
			}
			*ptr = '\0';
			bv.bv_len = ptr - bv.bv_val;

			ber_bvarray_add( &c->rvalue_vals, &bv );
			rc = 0;
		}
		}
		break;
	case LDAP_MOD_DELETE:
		if ( c->valx == -1 ) {
		/* Delete entire attribute */
			collect_info *ci;
			while (( ci = on->on_bi.bi_private )) {
				on->on_bi.bi_private = ci->ci_next;
				ch_free( ci->ci_dn.bv_val );
				ch_free( ci );
			}
		} else {
		/* Delete just one value */
			collect_info **cip, *ci;
			int i;
			cip = (collect_info **)&on->on_bi.bi_private;
			ci = *cip;
			for ( i=0; i < c->valx; i++ ) {
				cip = &ci->ci_next;
				ci = *cip;
			}
			*cip = ci->ci_next;
			ch_free( ci->ci_dn.bv_val );
			ch_free( ci );
		}
		rc = 0;
		break;
	case SLAP_CONFIG_ADD:
	case LDAP_MOD_ADD:
		{
		collect_info *ci;
		struct berval bv, dn;
		const char *text;
		int idx, count=0;
		char *arg;

		/* count delimiters in attribute argument */
		arg = strtok(c->argv[2], ",");
		while (arg!=NULL) {
			count++;
			arg = strtok(NULL, ",");
		}

		/* validate and normalize dn */
		ber_str2bv( c->argv[1], 0, 0, &bv );
		if ( dnNormalize( 0, NULL, NULL, &bv, &dn, NULL ) ) {
			snprintf( c->cr_msg, sizeof( c->cr_msg ), "%s invalid DN: \"%s\"",
				c->argv[0], c->argv[1] );
			Debug( LDAP_DEBUG_CONFIG|LDAP_DEBUG_NONE,
				"%s: %s\n", c->log, c->cr_msg, 0 );
			return ARG_BAD_CONF;
		}

		/* check for duplicate DNs */
		for ( ci = (collect_info *)on->on_bi.bi_private; ci;
			ci = ci->ci_next ) {
			/* If new DN is longest, there are no possible matches */
			if ( dn.bv_len > ci->ci_dn.bv_len ) {
				ci = NULL;
				break;
			}
			if ( bvmatch( &dn, &ci->ci_dn )) {
				break;
			}
		}
		if ( ci ) {
			snprintf( c->cr_msg, sizeof( c->cr_msg ), "%s DN already configured: \"%s\"",
				c->argv[0], c->argv[1] );
			Debug( LDAP_DEBUG_CONFIG|LDAP_DEBUG_NONE,
				"%s: %s\n", c->log, c->cr_msg, 0 );
			return ARG_BAD_CONF;
		}

		/* allocate config info with room for attribute array */
		ci = ch_malloc( sizeof( collect_info ) +
			sizeof( AttributeDescription * ) * count );

		/* load attribute description for attribute list */
		arg = c->argv[2];
		for( idx=0; idx<count; idx++) {
			ci->ci_ad[idx] = NULL;

			if ( slap_str2ad( arg, &ci->ci_ad[idx], &text ) ) {
				snprintf( c->cr_msg, sizeof( c->cr_msg ), 
					"%s attribute description unknown: \"%s\"",
					c->argv[0], arg);
				Debug( LDAP_DEBUG_CONFIG|LDAP_DEBUG_NONE,
					"%s: %s\n", c->log, c->cr_msg, 0 );
				ch_free( ci );
				return ARG_BAD_CONF;
			}
			while(*arg!='\0') {
				arg++; /* skip to end of argument */
			}
			if (idx<count-1) {
				arg++; /* skip inner delimiters */
			}
		}

		/* The on->on_bi.bi_private pointer can be used for
		 * anything this instance of the overlay needs.
		 */
		ci->ci_ad[count] = NULL;
		ci->ci_ad_num = count;
		ci->ci_dn = dn;

		/* creates list of ci's ordered by dn length */ 
		insert_ordered ( on, ci );

		/* New ci wasn't simply appended to end, adjust its
		 * position in the config entry's a_vals
		 */
		if ( c->ca_entry && ci->ci_next ) {
			Attribute *a = attr_find( c->ca_entry->e_attrs,
				collectcfg[0].ad );
			if ( a ) {
				struct berval bv, nbv;
				collect_info *c2 = (collect_info *)on->on_bi.bi_private;
				int i, j;
				for ( i=0; c2 != ci; i++, c2 = c2->ci_next );
				bv = a->a_vals[a->a_numvals-1];
				nbv = a->a_nvals[a->a_numvals-1];
				for ( j=a->a_numvals-1; j>i; j-- ) {
					a->a_vals[j] = a->a_vals[j-1];
					a->a_nvals[j] = a->a_nvals[j-1];
				}
				a->a_vals[j] = bv;
				a->a_nvals[j] = nbv;
			}
		}

		rc = 0;
		}
	}
	return rc;
}
Exemple #20
0
static int
pw2entry( Backend *be, struct passwd *pw, Entry *e )
{
    size_t		pwlen;
    struct berval	val;
    struct berval	bv;

    int		rc;

    /*
     * from pw we get pw_name and make it cn
     * give it an objectclass of person.
     */

    pwlen = strlen( pw->pw_name );
    val.bv_len = STRLENOF("uid=,") + ( pwlen + be->be_suffix[0].bv_len );
    val.bv_val = ch_malloc( val.bv_len + 1 );

    /* rdn attribute type should be a configuratable item */
    sprintf( val.bv_val, "uid=%s,%s",
             pw->pw_name, be->be_suffix[0].bv_val );

    rc = dnNormalize( 0, NULL, NULL, &val, &bv, NULL );
    if( rc != LDAP_SUCCESS ) {
        free( val.bv_val );
        return( -1 );
    }

    e->e_name = val;
    e->e_nname = bv;

    e->e_attrs = NULL;

    /* objectclasses should be configurable items */
    BER_BVSTR( &val, "person" );
    attr_merge_one( e, slap_schema.si_ad_objectClass, &val, NULL );

    BER_BVSTR( &val, "uidObject" );
    attr_merge_one( e, slap_schema.si_ad_objectClass, &val, NULL );

    val.bv_val = pw->pw_name;
    val.bv_len = pwlen;
    attr_merge_normalize_one( e, slap_schema.si_ad_uid, &val, NULL );	/* required by uidObject */
    attr_merge_normalize_one( e, slap_schema.si_ad_cn, &val, NULL );	/* required by person */
    attr_merge_normalize_one( e, ad_sn, &val, NULL );	/* required by person */

#ifdef HAVE_STRUCT_PASSWD_PW_GECOS
    /*
     * if gecos is present, add it as a cn. first process it
     * according to standard BSD usage. If the processed cn has
     * a space, use the tail as the surname.
     */
    if (pw->pw_gecos[0]) {
        char *s;

        ber_str2bv( pw->pw_gecos, 0, 0, &val );
        attr_merge_normalize_one( e, ad_desc, &val, NULL );

        s = ber_bvchr( &val, ',' );
        if ( s ) *s = '\0';

        s = ber_bvchr( &val, '&' );
        if ( s ) {
            char buf[1024];

            if( val.bv_len + pwlen < sizeof(buf) ) {
                int i = s - val.bv_val;
                strncpy( buf, val.bv_val, i );
                s = buf + i;
                strcpy( s, pw->pw_name );
                *s = TOUPPER((unsigned char)*s);
                strcat( s, val.bv_val + i + 1 );
                val.bv_val = buf;
            }
        }
        val.bv_len = strlen( val.bv_val );

        if ( val.bv_len && strcasecmp( val.bv_val, pw->pw_name ) ) {
            attr_merge_normalize_one( e, slap_schema.si_ad_cn, &val, NULL );
        }

        if ( ( s = strrchr(val.bv_val, ' ' ) ) ) {
            ber_str2bv( s + 1, 0, 0, &val );
            attr_merge_normalize_one( e, ad_sn, &val, NULL );
        }
    }
#endif /* HAVE_STRUCT_PASSWD_PW_GECOS */

    return( 0 );
}
Exemple #21
0
/*
 * I don't like this much, but we need two different
 * functions because different heap managers may be
 * in use in back-ldap/meta to reduce the amount of
 * calls to malloc routines, and some of the free()
 * routines may be macros with args
 */
int
rwm_dnattr_rewrite(
	Operation		*op,
	SlapReply		*rs,
	void			*cookie,
	BerVarray		a_vals,
	BerVarray		*pa_nvals )
{
	slap_overinst		*on = (slap_overinst *) op->o_bd->bd_info;
	struct ldaprwmap	*rwmap = 
			(struct ldaprwmap *)on->on_bi.bi_private;

	int			i, last;

	dncookie		dc;
	struct berval		dn = BER_BVNULL,
				ndn = BER_BVNULL;
	BerVarray		in;

	if ( a_vals ) {
		in = a_vals;

	} else {
		if ( pa_nvals == NULL || *pa_nvals == NULL ) {
			return LDAP_OTHER;
		}
		in = *pa_nvals;
	}

	/*
	 * Rewrite the dn if needed
	 */
	dc.rwmap = rwmap;
	dc.conn = op->o_conn;
	dc.rs = rs;
	dc.ctx = (char *)cookie;

	for ( last = 0; !BER_BVISNULL( &in[last] ); last++ );
	last--;
	if ( pa_nvals != NULL ) {
		if ( *pa_nvals == NULL ) {
			*pa_nvals = ch_malloc( ( last + 2 ) * sizeof(struct berval) );
			memset( *pa_nvals, 0, ( last + 2 ) * sizeof(struct berval) );
		}
	}

	for ( i = 0; !BER_BVISNULL( &in[i] ); i++ ) {
		int		rc;

		if ( a_vals ) {
			dn = in[i];
			if ( pa_nvals ) {
				ndn = (*pa_nvals)[i];
				rc = rwm_dn_massage_pretty_normalize( &dc, &in[i], &dn, &ndn );
			} else {
				rc = rwm_dn_massage_pretty( &dc, &in[i], &dn );
			}
		} else {
			ndn = in[i];
			rc = rwm_dn_massage_normalize( &dc, &in[i], &ndn );
		}

		switch ( rc ) {
		case LDAP_UNWILLING_TO_PERFORM:
			/*
			 * FIXME: need to check if it may be considered 
			 * legal to trim values when adding/modifying;
			 * it should be when searching (e.g. ACLs).
			 */
			ch_free( in[i].bv_val );
			if (last > i ) {
				in[i] = in[last];
				if ( a_vals && pa_nvals ) {
					(*pa_nvals)[i] = (*pa_nvals)[last];
				}
			}
			BER_BVZERO( &in[last] );
			if ( a_vals && pa_nvals ) {
				BER_BVZERO( &(*pa_nvals)[last] );
			}
			last--;
			break;
		
		case LDAP_SUCCESS:
			if ( a_vals ) {
				if ( !BER_BVISNULL( &dn ) && dn.bv_val != a_vals[i].bv_val ) {
					ch_free( a_vals[i].bv_val );
					a_vals[i] = dn;

					if ( pa_nvals ) {
						if ( !BER_BVISNULL( &(*pa_nvals)[i] ) ) {
							ch_free( (*pa_nvals)[i].bv_val );
						}
						(*pa_nvals)[i] = ndn;
					}
				}
				
			} else {
				if ( !BER_BVISNULL( &ndn ) && ndn.bv_val != (*pa_nvals)[i].bv_val ) {
					ch_free( (*pa_nvals)[i].bv_val );
					(*pa_nvals)[i] = ndn;
				}
			}
			break;

		default:
			/* leave attr untouched if massage failed */
			if ( a_vals && pa_nvals && BER_BVISNULL( &(*pa_nvals)[i] ) ) {
				dnNormalize( 0, NULL, NULL, &a_vals[i], &(*pa_nvals)[i], NULL );
			}
			break;
		}
	}
	
	return 0;
}
Exemple #22
0
static int
OpenLDAPaciPrettyNormal(
	struct berval	*val,
	struct berval	*out,
	void		*ctx,
	int		normalize )
{
	struct berval	oid = BER_BVNULL,
			scope = BER_BVNULL,
			rights = BER_BVNULL,
			nrights = BER_BVNULL,
			type = BER_BVNULL,
			ntype = BER_BVNULL,
			subject = BER_BVNULL,
			nsubject = BER_BVNULL;
	int		idx,
			rc = LDAP_SUCCESS,
			freesubject = 0,
			freetype = 0;
	char		*ptr;

	BER_BVZERO( out );

	if ( BER_BVISEMPTY( val ) ) {
		Debug( LDAP_DEBUG_ACL, "aciPrettyNormal: value is empty\n" );
		return LDAP_INVALID_SYNTAX;
	}

	/* oid: if valid, it's already normalized */
	if ( acl_get_part( val, 0, '#', &oid ) < 0 ||
		numericoidValidate( NULL, &oid ) != LDAP_SUCCESS )
	{
		Debug( LDAP_DEBUG_ACL, "aciPrettyNormal: invalid oid '%s'\n", oid.bv_val );
		return LDAP_INVALID_SYNTAX;
	}

	/* scope: normalize by replacing with OpenLDAPaciscopes */
	if ( acl_get_part( val, 1, '#', &scope ) < 0 ) {
		Debug( LDAP_DEBUG_ACL, "aciPrettyNormal: missing scope in '%s'\n", val->bv_val );
		return LDAP_INVALID_SYNTAX;
	}
	idx = bv_getcaseidx( &scope, OpenLDAPaciscopes );
	if ( idx == -1 ) {
		Debug( LDAP_DEBUG_ACL, "aciPrettyNormal: invalid scope '%s'\n", scope.bv_val );
		return LDAP_INVALID_SYNTAX;
	}
	scope = *OpenLDAPaciscopes[ idx ];

	/* rights */
	if ( acl_get_part( val, 2, '#', &rights ) < 0 ) {
		Debug( LDAP_DEBUG_ACL, "aciPrettyNormal: missing rights in '%s'\n", val->bv_val );
		return LDAP_INVALID_SYNTAX;
	}
	if ( OpenLDAPaciNormalizeRights( &rights, &nrights, ctx )
		!= LDAP_SUCCESS )
	{
		return LDAP_INVALID_SYNTAX;
	}

	/* type */
	if ( acl_get_part( val, 3, '#', &type ) < 0 ) {
		Debug( LDAP_DEBUG_ACL, "aciPrettyNormal: missing type in '%s'\n", val->bv_val );
		rc = LDAP_INVALID_SYNTAX;
		goto cleanup;
	}
	idx = bv_getcaseidx( &type, OpenLDAPacitypes );
	if ( idx == -1 ) {
		struct berval	isgr;

		if ( acl_get_part( &type, 0, '/', &isgr ) < 0 ) {
		        Debug( LDAP_DEBUG_ACL, "aciPrettyNormal: invalid type '%s'\n", type.bv_val );
			rc = LDAP_INVALID_SYNTAX;
			goto cleanup;
		}

		idx = bv_getcaseidx( &isgr, OpenLDAPacitypes );
		if ( idx == -1 || idx >= LAST_OPTIONAL ) {
		        Debug( LDAP_DEBUG_ACL, "aciPrettyNormal: invalid type '%s'\n", isgr.bv_val );
			rc = LDAP_INVALID_SYNTAX;
			goto cleanup;
		}
	}
	ntype = *OpenLDAPacitypes[ idx ];

	/* subject */
	bv_get_tail( val, &type, &subject );

	if ( BER_BVISEMPTY( &subject ) || subject.bv_val[ 0 ] != '#' ) {
	        Debug( LDAP_DEBUG_ACL, "aciPrettyNormal: missing subject in '%s'\n", val->bv_val );
		rc = LDAP_INVALID_SYNTAX;
		goto cleanup;
	}

	subject.bv_val++;
	subject.bv_len--;

	if ( idx < LAST_DNVALUED ) {
		/* FIXME: pass DN syntax? */
		if ( normalize ) {
			rc = dnNormalize( 0, NULL, NULL,
				&subject, &nsubject, ctx );
		} else {
			rc = dnPretty( NULL, &subject, &nsubject, ctx );
		}

		if ( rc == LDAP_SUCCESS ) {
			freesubject = 1;

		} else {
	                Debug( LDAP_DEBUG_ACL, "aciPrettyNormal: invalid subject dn '%s'\n", subject.bv_val );
			goto cleanup;
		}

		if ( OpenLDAPacitypes[ idx ] == &aci_bv[ ACI_BV_GROUP ]
			|| OpenLDAPacitypes[ idx ] == &aci_bv[ ACI_BV_ROLE ] )
		{
			/* do {group|role}/oc/at check */
			struct berval	ocbv = BER_BVNULL,
					atbv = BER_BVNULL;

			ocbv.bv_val = ber_bvchr( &type, '/' );
			if ( ocbv.bv_val != NULL ) {
				ObjectClass		*oc = NULL;
				AttributeDescription	*ad = NULL;
				const char		*text = NULL;
				int			rc;
				struct berval		bv;

				bv.bv_len = ntype.bv_len;

				ocbv.bv_val++;
				ocbv.bv_len = type.bv_len - ( ocbv.bv_val - type.bv_val );

				atbv.bv_val = ber_bvchr( &ocbv, '/' );
				if ( atbv.bv_val != NULL ) {
					atbv.bv_val++;
					atbv.bv_len = type.bv_len
						- ( atbv.bv_val - type.bv_val );
					ocbv.bv_len = atbv.bv_val - ocbv.bv_val - 1;

					rc = slap_bv2ad( &atbv, &ad, &text );
					if ( rc != LDAP_SUCCESS ) {
	                                        Debug( LDAP_DEBUG_ACL, "aciPrettyNormal: unknown group attribute '%s'\n", atbv.bv_val );
						rc = LDAP_INVALID_SYNTAX;
						goto cleanup;
					}

					bv.bv_len += STRLENOF( "/" ) + ad->ad_cname.bv_len;
				}

				oc = oc_bvfind( &ocbv );
				if ( oc == NULL ) {
                                        Debug( LDAP_DEBUG_ACL, "aciPrettyNormal: invalid group '%s'\n", ocbv.bv_val );
					rc = LDAP_INVALID_SYNTAX;
					goto cleanup;
				}

				bv.bv_len += STRLENOF( "/" ) + oc->soc_cname.bv_len;
				bv.bv_val = ber_memalloc_x( bv.bv_len + 1, ctx );

				ptr = bv.bv_val;
				ptr = lutil_strncopy( ptr, ntype.bv_val, ntype.bv_len );
				ptr[ 0 ] = '/';
				ptr++;
				ptr = lutil_strncopy( ptr,
					oc->soc_cname.bv_val,
					oc->soc_cname.bv_len );
				if ( ad != NULL ) {
					ptr[ 0 ] = '/';
					ptr++;
					ptr = lutil_strncopy( ptr,
						ad->ad_cname.bv_val,
						ad->ad_cname.bv_len );
				}
				ptr[ 0 ] = '\0';

				ntype = bv;
				freetype = 1;
			}
		}

	} else if ( OpenLDAPacitypes[ idx ] == &aci_bv[ ACI_BV_DNATTR ] ) {
		AttributeDescription	*ad = NULL;
		const char		*text = NULL;
		int			rc;

		rc = slap_bv2ad( &subject, &ad, &text );
		if ( rc != LDAP_SUCCESS ) {
                        Debug( LDAP_DEBUG_ACL, "aciPrettyNormal: unknown dn attribute '%s'\n", subject.bv_val );
			rc = LDAP_INVALID_SYNTAX;
			goto cleanup;
		}

		if ( ad->ad_type->sat_syntax != slap_schema.si_syn_distinguishedName ) {
			/* FIXME: allow nameAndOptionalUID? */
                        Debug( LDAP_DEBUG_ACL, "aciPrettyNormal: wrong syntax for dn attribute '%s'\n", subject.bv_val );
			rc = LDAP_INVALID_SYNTAX;
			goto cleanup;
		}

		nsubject = ad->ad_cname;

	} else if ( OpenLDAPacitypes[ idx ] == &aci_bv[ ACI_BV_SET ]
		|| OpenLDAPacitypes[ idx ] == &aci_bv[ ACI_BV_SET_REF ] )
	{
		/* NOTE: dunno how to normalize it... */
		nsubject = subject;
	}


	out->bv_len =
		oid.bv_len + STRLENOF( "#" )
		+ scope.bv_len + STRLENOF( "#" )
		+ nrights.bv_len + STRLENOF( "#" )
		+ ntype.bv_len + STRLENOF( "#" )
		+ nsubject.bv_len;

	out->bv_val = ber_memalloc_x( out->bv_len + 1, ctx );
	ptr = lutil_strncopy( out->bv_val, oid.bv_val, oid.bv_len );
	ptr[ 0 ] = '#';
	ptr++;
	ptr = lutil_strncopy( ptr, scope.bv_val, scope.bv_len );
	ptr[ 0 ] = '#';
	ptr++;
	ptr = lutil_strncopy( ptr, nrights.bv_val, nrights.bv_len );
	ptr[ 0 ] = '#';
	ptr++;
	ptr = lutil_strncopy( ptr, ntype.bv_val, ntype.bv_len );
	ptr[ 0 ] = '#';
	ptr++;
	if ( !BER_BVISNULL( &nsubject ) ) {
		ptr = lutil_strncopy( ptr, nsubject.bv_val, nsubject.bv_len );
	}
	ptr[ 0 ] = '\0';

cleanup:;
	if ( freesubject ) {
		ber_memfree_x( nsubject.bv_val, ctx );
	}

	if ( freetype ) {
		ber_memfree_x( ntype.bv_val, ctx );
	}

	if ( !BER_BVISNULL( &nrights ) ) {
		ber_memfree_x( nrights.bv_val, ctx );
	}

	return rc;
}
Exemple #23
0
static int
proxyOld_parse(
	Operation *op,
	SlapReply *rs,
	LDAPControl *ctrl )
{
	int rc;
	BerElement	*ber;
	ber_tag_t	tag;
	struct berval dn = BER_BVNULL;
	struct berval authzDN = BER_BVNULL;


	/* We hijack the flag for the new control. Clearly only one or the
	 * other can be used at any given time.
	 */
	if ( op->o_proxy_authz != SLAP_CONTROL_NONE ) {
		rs->sr_text = "proxy authorization control specified multiple times";
		return LDAP_PROTOCOL_ERROR;
	}

	op->o_proxy_authz = ctrl->ldctl_iscritical
		? SLAP_CONTROL_CRITICAL
		: SLAP_CONTROL_NONCRITICAL;

	/* Parse the control value
	 *  proxyAuthzControlValue ::= SEQUENCE {
	 *		proxyDN	LDAPDN
	 *	}
	 */
	ber = ber_init( &ctrl->ldctl_value );
	if ( ber == NULL ) {
		rs->sr_text = "ber_init failed";
		return LDAP_OTHER;
	}

	tag = ber_scanf( ber, "{m}", &dn );

	if ( tag == LBER_ERROR ) {
		rs->sr_text = "proxyOld control could not be decoded";
		rc = LDAP_OTHER;
		goto done;
	}
	if ( BER_BVISEMPTY( &dn )) {
		Debug( LDAP_DEBUG_TRACE,
			"proxyOld_parse: conn=%lu anonymous\n",
				op->o_connid, 0, 0 );
		authzDN.bv_val = ch_strdup("");
	} else {
		Debug( LDAP_DEBUG_ARGS,
			"proxyOld_parse: conn %lu ctrl DN=\"%s\"\n",
				op->o_connid, dn.bv_val, 0 );
		rc = dnNormalize( 0, NULL, NULL, &dn, &authzDN, op->o_tmpmemctx );
		if ( rc != LDAP_SUCCESS ) {
			goto done;
		}
		rc = slap_sasl_authorized( op, &op->o_ndn, &authzDN );
		if ( rc ) {
			op->o_tmpfree( authzDN.bv_val, op->o_tmpmemctx );
			rs->sr_text = "not authorized to assume identity";
			/* new spec uses LDAP_PROXY_AUTHZ_FAILURE */
			rc = LDAP_INSUFFICIENT_ACCESS;
			goto done;
		}
	}
	free( op->o_ndn.bv_val );
	free( op->o_dn.bv_val );
	op->o_ndn = authzDN;
	ber_dupbv( &op->o_dn, &authzDN );

	Statslog( LDAP_DEBUG_STATS, "conn=%lu op=%lu PROXYOLD dn=\"%s\"\n",
		op->o_connid, op->o_opid,
		authzDN.bv_len ? authzDN.bv_val : "anonymous", 0, 0 );
	rc = LDAP_SUCCESS;
done:
	ber_free( ber, 1 );
	return rc;
}
Exemple #24
0
int
dnssrv_back_search(
    Operation	*op,
    SlapReply	*rs )
{
	int i;
	int rc;
	char *domain = NULL;
	char *hostlist = NULL;
	char **hosts = NULL;
	char *refdn;
	struct berval nrefdn = BER_BVNULL;
	BerVarray urls = NULL;
	int manageDSAit;

	rs->sr_ref = NULL;

	if ( BER_BVISEMPTY( &op->o_req_ndn ) ) {
		/* FIXME: need some means to determine whether the database
		 * is a glue instance; if we got here with empty DN, then
		 * we passed this same test in dnssrv_back_referrals() */
		if ( !SLAP_GLUE_INSTANCE( op->o_bd ) ) {
			rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
			rs->sr_text = "DNS SRV operation upon null (empty) DN disallowed";

		} else {
			rs->sr_err = LDAP_SUCCESS;
		}
		goto done;
	}

	manageDSAit = get_manageDSAit( op );
	/*
	 * FIXME: we may return a referral if manageDSAit is not set
	 */
	if ( !manageDSAit ) {
		send_ldap_error( op, rs, LDAP_UNWILLING_TO_PERFORM,
				"manageDSAit must be set" );
		goto done;
	}

	if( ldap_dn2domain( op->o_req_dn.bv_val, &domain ) || domain == NULL ) {
		rs->sr_err = LDAP_REFERRAL;
		rs->sr_ref = default_referral;
		send_ldap_result( op, rs );
		rs->sr_ref = NULL;
		goto done;
	}

	Debug( LDAP_DEBUG_TRACE, "DNSSRV: dn=\"%s\" -> domain=\"%s\"\n",
		op->o_req_dn.bv_len ? op->o_req_dn.bv_val : "", domain );

	if( ( rc = ldap_domain2hostlist( domain, &hostlist ) ) ) {
		Debug( LDAP_DEBUG_TRACE, "DNSSRV: domain2hostlist returned %d\n",
			rc );
		send_ldap_error( op, rs, LDAP_NO_SUCH_OBJECT,
			"no DNS SRV RR available for DN" );
		goto done;
	}

	hosts = ldap_str2charray( hostlist, " " );

	if( hosts == NULL ) {
		Debug( LDAP_DEBUG_TRACE, "DNSSRV: str2charray error\n" );
		send_ldap_error( op, rs, LDAP_OTHER,
			"problem processing DNS SRV records for DN" );
		goto done;
	}

	for( i=0; hosts[i] != NULL; i++) {
		struct berval url;

		url.bv_len = STRLENOF( "ldap://" ) + strlen(hosts[i]);
		url.bv_val = ch_malloc( url.bv_len + 1 );

		strcpy( url.bv_val, "ldap://" );
		strcpy( &url.bv_val[STRLENOF( "ldap://" )], hosts[i] );

		if( ber_bvarray_add( &urls, &url ) < 0 ) {
			free( url.bv_val );
			send_ldap_error( op, rs, LDAP_OTHER,
			"problem processing DNS SRV records for DN" );
			goto done;
		}
	}

	Debug( LDAP_DEBUG_STATS,
	    "%s DNSSRV p=%d dn=\"%s\" url=\"%s\"\n",
	    op->o_log_prefix, op->o_protocol,
		op->o_req_dn.bv_len ? op->o_req_dn.bv_val : "", urls[0].bv_val );

	Debug( LDAP_DEBUG_TRACE,
		"DNSSRV: ManageDSAit scope=%d dn=\"%s\" -> url=\"%s\"\n",
		op->oq_search.rs_scope,
		op->o_req_dn.bv_len ? op->o_req_dn.bv_val : "",
		urls[0].bv_val );

	rc = ldap_domain2dn(domain, &refdn);

	if( rc != LDAP_SUCCESS ) {
		send_ldap_error( op, rs, LDAP_OTHER,
			"DNS SRV problem processing manageDSAit control" );
		goto done;

	} else {
		struct berval bv;
		bv.bv_val = refdn;
		bv.bv_len = strlen( refdn );

		rc = dnNormalize( 0, NULL, NULL, &bv, &nrefdn, op->o_tmpmemctx );
		if( rc != LDAP_SUCCESS ) {
			send_ldap_error( op, rs, LDAP_OTHER,
				"DNS SRV problem processing manageDSAit control" );
			goto done;
		}
	}

	if( !dn_match( &nrefdn, &op->o_req_ndn ) ) {
		/* requested dn is subordinate */

		Debug( LDAP_DEBUG_TRACE,
			"DNSSRV: dn=\"%s\" subordinate to refdn=\"%s\"\n",
			op->o_req_dn.bv_len ? op->o_req_dn.bv_val : "",
			refdn == NULL ? "" : refdn );

		rs->sr_matched = refdn;
		rs->sr_err = LDAP_NO_SUCH_OBJECT;
		send_ldap_result( op, rs );
		rs->sr_matched = NULL;

	} else if ( op->oq_search.rs_scope == LDAP_SCOPE_ONELEVEL ) {
		send_ldap_error( op, rs, LDAP_SUCCESS, NULL );

	} else {
		Entry e = { 0 };
		AttributeDescription *ad_objectClass
			= slap_schema.si_ad_objectClass;
		AttributeDescription *ad_ref = slap_schema.si_ad_ref;
		e.e_name.bv_val = ch_strdup( op->o_req_dn.bv_val );
		e.e_name.bv_len = op->o_req_dn.bv_len;
		e.e_nname.bv_val = ch_strdup( op->o_req_ndn.bv_val );
		e.e_nname.bv_len = op->o_req_ndn.bv_len;

		e.e_attrs = NULL;
		e.e_private = NULL;

		attr_merge_one( &e, ad_objectClass, &slap_schema.si_oc_referral->soc_cname, NULL );
		attr_merge_one( &e, ad_objectClass, &slap_schema.si_oc_extensibleObject->soc_cname, NULL );

		if ( ad_dc ) {
			char		*p;
			struct berval	bv;

			bv.bv_val = domain;

			p = strchr( bv.bv_val, '.' );
					
			if ( p == bv.bv_val ) {
				bv.bv_len = 1;

			} else if ( p != NULL ) {
				bv.bv_len = p - bv.bv_val;

			} else {
				bv.bv_len = strlen( bv.bv_val );
			}

			attr_merge_normalize_one( &e, ad_dc, &bv, NULL );
		}

		if ( ad_associatedDomain ) {
			struct berval	bv;

			ber_str2bv( domain, 0, 0, &bv );
			attr_merge_normalize_one( &e, ad_associatedDomain, &bv, NULL );
		}

		attr_merge_normalize_one( &e, ad_ref, urls, NULL );

		rc = test_filter( op, &e, op->oq_search.rs_filter ); 

		if( rc == LDAP_COMPARE_TRUE ) {
			rs->sr_entry = &e;
			rs->sr_attrs = op->oq_search.rs_attrs;
			rs->sr_flags = REP_ENTRY_MODIFIABLE;
			send_search_entry( op, rs );
			rs->sr_entry = NULL;
			rs->sr_attrs = NULL;
			rs->sr_flags = 0;
		}

		entry_clean( &e );

		rs->sr_err = LDAP_SUCCESS;
		send_ldap_result( op, rs );
	}

	free( refdn );
	if ( nrefdn.bv_val ) free( nrefdn.bv_val );

done:
	if( domain != NULL ) ch_free( domain );
	if( hostlist != NULL ) ch_free( hostlist );
	if( hosts != NULL ) ldap_charray_free( hosts );
	if( urls != NULL ) ber_bvarray_free( urls );
	return 0;
}
Exemple #25
0
static int
adremap_cf_dnv(ConfigArgs *c)
{
	BackendDB *be = (BackendDB *)c->be;
	slap_overinst *on = (slap_overinst *)c->bi;
	adremap_info *ai = on->on_bi.bi_private;
	adremap_dnv *ad, **a2;
	int rc = ARG_BAD_CONF;

	switch(c->op) {
	case SLAP_CONFIG_EMIT:
		for (ad = ai->ai_dnv; ad; ad=ad->ad_next) {
			char *ptr;
			struct berval bv;
			bv.bv_len = ad->ad_dnattr->ad_cname.bv_len + ad->ad_deref->ad_cname.bv_len + ad->ad_newattr->ad_cname.bv_len + 2;
			bv.bv_len += ad->ad_group->soc_cname.bv_len + ad->ad_mapgrp->soc_cname.bv_len + ad->ad_refgrp->soc_cname.bv_len + 3;
			bv.bv_len += ad->ad_refbase.bv_len + 3;
			bv.bv_val = ch_malloc(bv.bv_len + 1);
			ptr = lutil_strcopy(bv.bv_val, ad->ad_dnattr->ad_cname.bv_val);
			*ptr++ = ' ';
			ptr = lutil_strcopy(ptr, ad->ad_deref->ad_cname.bv_val);
			*ptr++ = ' ';
			ptr = lutil_strcopy(ptr, ad->ad_newattr->ad_cname.bv_val);
			*ptr++ = ' ';
			ptr = lutil_strcopy(ptr, ad->ad_group->soc_cname.bv_val);
			*ptr++ = ' ';
			ptr = lutil_strcopy(ptr, ad->ad_mapgrp->soc_cname.bv_val);
			*ptr++ = ' ';
			ptr = lutil_strcopy(ptr, ad->ad_refgrp->soc_cname.bv_val);
			*ptr++ = ' ';
			*ptr++ = '"';
			ptr = lutil_strcopy(ptr, ad->ad_refbase.bv_val);
			*ptr++ = '"';
			*ptr = '\0';
			ber_bvarray_add(&c->rvalue_vals, &bv);
		}
		if (ai->ai_dnv) rc = 0;
		break;
	case LDAP_MOD_DELETE:
		if (c->valx < 0) {
			for (ad = ai->ai_dnv; ad; ad=ai->ai_dnv) {
				ai->ai_dnv = ad->ad_next;
				ch_free(ad);
			}
		} else {
			int i;
			for (i=0, a2 = &ai->ai_dnv; i<c->valx; i++, a2 = &(*a2)->ad_next);
			ad = *a2;
			*a2 = ad->ad_next;
			ch_free(ad);
		}
		rc = 0;
		break;
	default: {
		const char *text;
		adremap_dnv av = {0};
		struct berval dn;
		rc = slap_str2ad(c->argv[1], &av.ad_dnattr, &text);
		if (rc) break;
		if (av.ad_dnattr->ad_type->sat_syntax != slap_schema.si_syn_distinguishedName) {
			rc = 1;
			snprintf(c->cr_msg, sizeof(c->cr_msg), "<%s> not a DN-valued attribute",
				c->argv[0]);
			Debug(LDAP_DEBUG_ANY, "%s: %s(%s)\n", c->log, c->cr_msg, c->argv[1]);
			break;
		}
		rc = slap_str2ad(c->argv[2], &av.ad_deref, &text);
		if (rc) break;
		rc = slap_str2ad(c->argv[3], &av.ad_newattr, &text);
		if (rc) break;
		av.ad_group = oc_find(c->argv[4]);
		if (!av.ad_group) {
			rc = 1;
			break;
		}
		av.ad_mapgrp = oc_find(c->argv[5]);
		if (!av.ad_mapgrp) {
			rc = 1;
			break;
		}
		av.ad_refgrp = oc_find(c->argv[6]);
		if (!av.ad_refgrp) {
			rc = 1;
			break;
		}
		ber_str2bv(c->argv[7], 0, 0, &dn);
		rc = dnNormalize(0, NULL, NULL, &dn, &av.ad_refbase, NULL);
		if (rc) break;

		for (a2 = &ai->ai_dnv; *a2; a2 = &(*a2)->ad_next);
		ad = ch_malloc(sizeof(adremap_dnv));
		ad->ad_next = NULL;
		ad->ad_dnattr = av.ad_dnattr;
		ad->ad_deref = av.ad_deref;
		ad->ad_newattr = av.ad_newattr;
		ad->ad_group = av.ad_group;
		ad->ad_mapgrp = av.ad_mapgrp;
		ad->ad_refgrp = av.ad_refgrp;
		ad->ad_refbase = av.ad_refbase;
		*a2 = ad;
		break;
		}
	}
	return rc;
}