Beispiel #1
0
void
do_compare( Slapi_PBlock *pb )
{
	BerElement	*ber = pb->pb_op->o_ber;
	char		*rawdn = NULL;
	const char	*dn = NULL;
	struct ava	ava = {0};
	Slapi_Backend		*be = NULL;
	int		err;
	Slapi_DN sdn;
	Slapi_Entry *referral = NULL;
	char errorbuf[SLAPI_DSE_RETURNTEXT_SIZE];

	slapi_log_err(SLAPI_LOG_TRACE, "do_compare", "=>\n");

	/* count the compare request */
	slapi_counter_increment(g_get_global_snmp_vars()->ops_tbl.dsCompareOps);

    /* have to init this here so we can "done" it below if we short circuit */
    slapi_sdn_init(&sdn);

	/*
	 * Parse the compare request.  It looks like this:
	 *
	 *	CompareRequest := [APPLICATION 14] SEQUENCE {
	 *		entry	DistinguishedName,
	 *		ava	SEQUENCE {
	 *			type	AttributeType,
	 *			value	AttributeValue
	 *		}
	 *	}
	 */

	if ( ber_scanf( ber, "{a{ao}}", &rawdn, &ava.ava_type,
	    &ava.ava_value ) == LBER_ERROR ) {
		slapi_log_err(SLAPI_LOG_ERR,
		    "do_compare", "ber_scanf failed (op=Compare; params=DN,Type,Value)\n");
		send_ldap_result( pb, LDAP_PROTOCOL_ERROR, NULL, NULL, 0,
			NULL );
		goto free_and_return;
	}
	/* Check if we should be performing strict validation. */
	if (config_get_dn_validate_strict()) {
		/* check that the dn is formatted correctly */
		err = slapi_dn_syntax_check(pb, rawdn, 1);
		if (err) { /* syntax check failed */
			op_shared_log_error_access(pb, "CMP",
							rawdn?rawdn:"", "strict: invalid dn");
			send_ldap_result(pb, LDAP_INVALID_DN_SYNTAX, 
							 NULL, "invalid dn", 0, NULL);
			slapi_ch_free((void **) &rawdn);
			return;
		}
	}
	slapi_sdn_init_dn_passin(&sdn, rawdn);
	dn = slapi_sdn_get_dn(&sdn);
    if (rawdn && (strlen(rawdn) > 0) && (NULL == dn)) {
        /* normalization failed */
        op_shared_log_error_access(pb, "CMP", rawdn, "invalid dn");
        send_ldap_result(pb, LDAP_INVALID_DN_SYNTAX, NULL,
                         "invalid dn", 0, NULL);
        slapi_sdn_done(&sdn);
        return;
    }
	/*
	 * in LDAPv3 there can be optional control extensions on
	 * the end of an LDAPMessage. we need to read them in and
	 * pass them to the backend.
	 */
	if ( (err = get_ldapmessage_controls( pb, ber, NULL )) != 0 ) {
		send_ldap_result( pb, err, NULL, NULL, 0, NULL );
		goto free_and_return;
	}

	/* target spec is used to decide which plugins are applicable for the operation */
	operation_set_target_spec (pb->pb_op, &sdn);

	slapi_log_err(SLAPI_LOG_ARGS, "do_compare: dn (%s) attr (%s)\n",
	    rawdn, ava.ava_type, 0 );

	slapi_log_access( LDAP_DEBUG_STATS,
	    "conn=%" NSPRIu64 " op=%d CMP dn=\"%s\" attr=\"%s\"\n",
	    pb->pb_conn->c_connid, pb->pb_op->o_opid, dn, ava.ava_type );

	/*
	 * We could be serving multiple database backends.  Select the
	 * appropriate one.
	 */
	if ((err = slapi_mapping_tree_select(pb, &be, &referral, errorbuf, sizeof(errorbuf))) != LDAP_SUCCESS) {
		send_ldap_result(pb, err, NULL, errorbuf, 0, NULL);
		be = NULL;
		goto free_and_return;
	}

	if (referral)
	{
		int managedsait;

		slapi_pblock_get(pb, SLAPI_MANAGEDSAIT, &managedsait);
		if (managedsait)
		{
			send_ldap_result(pb, LDAP_UNWILLING_TO_PERFORM, NULL,
					"cannot compare referral", 0, NULL);
			slapi_entry_free(referral);
			goto free_and_return;
		}
	
		send_referrals_from_entry(pb,referral);
		slapi_entry_free(referral);
		goto free_and_return;
	}

	if ( be->be_compare != NULL ) {
		int		isroot;
		    
		slapi_pblock_set( pb, SLAPI_BACKEND, be );
		isroot = pb->pb_op->o_isroot;

		slapi_pblock_set( pb, SLAPI_REQUESTOR_ISROOT, &isroot );
		/* EXCEPTION: compare target does not allocate memory. */
		/* target never be modified by plugins. */
		slapi_pblock_set( pb, SLAPI_COMPARE_TARGET_SDN, (void*)&sdn );
		slapi_pblock_set( pb, SLAPI_COMPARE_TYPE, ava.ava_type);
		slapi_pblock_set( pb, SLAPI_COMPARE_VALUE, &ava.ava_value );
		/*
		 * call the pre-compare plugins. if they succeed, call
		 * the backend compare function. then call the
		 * post-compare plugins.
		 */
		if ( plugin_call_plugins( pb,
				SLAPI_PLUGIN_PRE_COMPARE_FN ) == 0 ) {
			int	rc;

			slapi_pblock_set( pb, SLAPI_PLUGIN, be->be_database );
			set_db_default_result_handlers(pb);
			rc = (*be->be_compare)( pb );

			slapi_pblock_set( pb, SLAPI_PLUGIN_OPRETURN, &rc );
			plugin_call_plugins( pb, SLAPI_PLUGIN_POST_COMPARE_FN );
		}
	} else {
		send_ldap_result( pb, LDAP_UNWILLING_TO_PERFORM, NULL,
		    "Function not implemented", 0, NULL );
	}

free_and_return:;
	if (be)
		slapi_be_Unlock(be);
	slapi_sdn_done(&sdn);
	ava_done( &ava );
}
Beispiel #2
0
/* This function is called to process operation that come over external connections */
void
do_modrdn( Slapi_PBlock *pb )
{
	Slapi_Operation *operation;
	BerElement	*ber;
	char		*rawdn = NULL, *rawnewsuperior = NULL;
	const char	*dn = NULL, *newsuperior = NULL;
	char		*newrdn = NULL;
	int		err = 0, deloldrdn = 0;
	ber_len_t	len = 0;
	char		*newdn = NULL;
	char		*parent = NULL;
	Slapi_DN	sdn;
	Slapi_DN	snewdn;
	Slapi_DN	*snewsuperior = NULL;

	LDAPDebug( LDAP_DEBUG_TRACE, "do_modrdn\n", 0, 0, 0 );

	/* count the modrdn request */
	slapi_counter_increment(g_get_global_snmp_vars()->ops_tbl.dsModifyRDNOps);

	slapi_pblock_get( pb, SLAPI_OPERATION, &operation);
	ber = operation->o_ber;

	slapi_sdn_init(&sdn);
	slapi_sdn_init(&snewdn);

	/*
	 * Parse the modrdn request.  It looks like this:
	 *
	 *	ModifyRDNRequest := SEQUENCE {
	 *		entry		    DistinguishedName,
	 *		newrdn		    RelativeDistinguishedName,
	 *		deleteoldrdn	    BOOLEAN,
	 *		newSuperior	[0] LDAPDN OPTIONAL -- v3 only
	 *	}
	 */

	if (ber_scanf(ber, "{aab", &rawdn, &newrdn, &deloldrdn) == LBER_ERROR) {
		LDAPDebug( LDAP_DEBUG_ANY,
		    "ber_scanf failed (op=ModRDN; params=DN,newRDN,deleteOldRDN)\n",
		    0, 0, 0 );
		op_shared_log_error_access (pb, "MODRDN", "???", "decoding error");
		send_ldap_result( pb, LDAP_PROTOCOL_ERROR, NULL,
		    "unable to decode DN, newRDN, or deleteOldRDN parameters",
		    0, NULL );
        goto free_and_return;
	}

	if ( ber_peek_tag( ber, &len ) == LDAP_TAG_NEWSUPERIOR ) {
		/* This "len" is not used... */
		if ( pb->pb_conn->c_ldapversion < LDAP_VERSION3 ) {
			LDAPDebug( LDAP_DEBUG_ANY,
			    "got newSuperior in LDAPv2 modrdn op\n", 0, 0, 0 );
			op_shared_log_error_access (pb, "MODRDN",
										rawdn?rawdn:"", "decoding error");
			send_ldap_result( pb, LDAP_PROTOCOL_ERROR, NULL,
			    "received newSuperior in LDAPv2 modrdn", 0, NULL );
			slapi_ch_free_string( &rawdn );
			slapi_ch_free_string( &newrdn );
			goto free_and_return;
		}
		if ( ber_scanf( ber, "a", &rawnewsuperior ) == LBER_ERROR ) {
			LDAPDebug( LDAP_DEBUG_ANY,
			    "ber_scanf failed (op=ModRDN; params=newSuperior)\n",
			    0, 0, 0 );
			op_shared_log_error_access (pb, "MODRDN", rawdn, "decoding error");
			send_ldap_result( pb, LDAP_PROTOCOL_ERROR, NULL,
			    "unable to decode newSuperior parameter", 0, NULL );
			slapi_ch_free_string( &rawdn );
			slapi_ch_free_string( &newrdn );
			goto free_and_return;
		}
	}

	/* Check if we should be performing strict validation. */
	if (config_get_dn_validate_strict()) {
		/* check that the dn is formatted correctly */
		err = slapi_dn_syntax_check(pb, rawdn, 1);
		if (err) { /* syntax check failed */
			op_shared_log_error_access(pb, "MODRDN", rawdn?rawdn:"",
							"strict: invalid dn");
			send_ldap_result(pb, LDAP_INVALID_DN_SYNTAX, 
							 NULL, "invalid dn", 0, NULL);
			slapi_ch_free_string( &rawdn );
			slapi_ch_free_string( &newrdn );
			slapi_ch_free_string( &rawnewsuperior );
			goto free_and_return;
		}
		/* check that the new rdn is formatted correctly */
		err = slapi_dn_syntax_check(pb, newrdn, 1);
		if (err) { /* syntax check failed */
			op_shared_log_error_access(pb, "MODRDN", newrdn?newrdn:"", 
							"strict: invalid new rdn");
			send_ldap_result(pb, LDAP_INVALID_DN_SYNTAX, 
							 NULL, "invalid new rdn", 0, NULL);
			slapi_ch_free_string( &rawdn );
			slapi_ch_free_string( &newrdn );
			slapi_ch_free_string( &rawnewsuperior );
			goto free_and_return;
		}
	}
	slapi_sdn_init_dn_passin(&sdn, rawdn);
	dn = slapi_sdn_get_dn(&sdn);
	if (rawdn && (strlen(rawdn) > 0) && (NULL == dn)) {
		/* normalization failed */
		op_shared_log_error_access(pb, "MODRDN", rawdn, "invalid dn");
		send_ldap_result(pb, LDAP_INVALID_DN_SYNTAX, NULL, 
		                 "invalid dn", 0, NULL);
		slapi_ch_free_string( &newrdn );
		slapi_ch_free_string( &rawnewsuperior );
		goto free_and_return;
	}

	if (rawnewsuperior) {
		if (config_get_dn_validate_strict()) {
			/* check that the dn is formatted correctly */
			err = slapi_dn_syntax_check(pb, rawnewsuperior, 1);
			if (err) { /* syntax check failed */
				op_shared_log_error_access(pb, "MODRDN", rawnewsuperior,
							"strict: invalid new superior");
				send_ldap_result(pb, LDAP_INVALID_DN_SYNTAX, 
								 NULL, "invalid new superior", 0, NULL);
				slapi_ch_free_string( &rawnewsuperior );
				goto free_and_return;
			}
		}
		snewsuperior = slapi_sdn_new_dn_passin(rawnewsuperior);
		newsuperior = slapi_sdn_get_dn(snewsuperior);
	}

	/*
	 * If newsuperior is myself or my descendent, the modrdn should fail.
	 * Note: need to check the case newrdn is given, and newsuperior
	 * uses the newrdn, as well.
	 */ 
	parent = slapi_dn_parent(slapi_sdn_get_ndn(&sdn));
	newdn = slapi_ch_smprintf("%s,%s", newrdn, parent);
	/* slapi_sdn_init_normdn_passin expects normalized but NOT
	 * decapitalized dn */
	slapi_sdn_init_dn_passin(&snewdn, newdn);
	if (0 == slapi_sdn_compare(&sdn, snewsuperior) ||
	    0 == slapi_sdn_compare(&snewdn, snewsuperior)) {
		op_shared_log_error_access(pb, "MODRDN", newsuperior,
						 "new superior is identical to the entry dn");
		send_ldap_result(pb, LDAP_UNWILLING_TO_PERFORM, NULL,
						 "new superior is identical to the entry dn", 0, NULL);
		goto free_and_return;
	}
	if (slapi_sdn_issuffix(snewsuperior, &sdn) ||
	    slapi_sdn_issuffix(snewsuperior, &snewdn)) {
		/* E.g.,
		 * newsuperior: ou=sub,ou=people,dc=example,dc=com
		 * dn: ou=people,dc=example,dc=com
		 */
		op_shared_log_error_access(pb, "MODRDN", newsuperior,
						 "new superior is descendent of the entry");
		send_ldap_result(pb, LDAP_UNWILLING_TO_PERFORM, NULL,
						 "new superior is descendent of the entry", 0, NULL);
		goto free_and_return;
	}

	/*
	 * in LDAPv3 there can be optional control extensions on
	 * the end of an LDAPMessage. we need to read them in and
	 * pass them to the backend.
	 */
	if ( (err = get_ldapmessage_controls( pb, ber, NULL )) != 0 ) {
		op_shared_log_error_access (pb, "MODRDN", dn, "failed to decode LDAP controls");
		send_ldap_result( pb, err, NULL, NULL, 0, NULL );
		goto free_and_return;
	}

	LDAPDebug( LDAP_DEBUG_ARGS,
			   "do_modrdn: dn (%s) newrdn (%s) deloldrdn (%d)\n", dn, newrdn,
			   deloldrdn );

	slapi_pblock_set( pb, SLAPI_REQUESTOR_ISROOT, &pb->pb_op->o_isroot );
	/* dn, newrdn and newsuperior are all normalized */
	slapi_pblock_set( pb, SLAPI_ORIGINAL_TARGET,
	                  (void *)slapi_sdn_get_udn(&sdn) );
	slapi_pblock_set( pb, SLAPI_MODRDN_TARGET_SDN, &sdn );
	slapi_pblock_set( pb, SLAPI_MODRDN_NEWRDN, (void *)newrdn );
	slapi_pblock_set( pb, SLAPI_MODRDN_NEWSUPERIOR_SDN, (void *)snewsuperior );
	slapi_pblock_set( pb, SLAPI_MODRDN_DELOLDRDN, &deloldrdn );

	op_shared_rename(pb, 0 /* do not pass in ownership of string arguments */ );

free_and_return:
	slapi_sdn_done(&sdn);
	slapi_ch_free_string(&newrdn);
	slapi_sdn_free(&snewsuperior);
	slapi_sdn_done(&snewdn);
	slapi_ch_free_string(&parent);

	return;
}
Beispiel #3
0
/* This function is called to process operation that come over external connections */
void
do_add( Slapi_PBlock *pb )
{
	Slapi_Operation *operation;
	BerElement		*ber;
	char			*last;
	ber_len_t		len = LBER_ERROR;
	ber_tag_t		tag;
	Slapi_Entry		*e = NULL;
	int			err;
	int			rc;
	PRBool  searchsubentry=PR_TRUE;

	slapi_log_err(SLAPI_LOG_TRACE, "do_add", "==>\n");

	slapi_pblock_get( pb, SLAPI_OPERATION, &operation);
    ber = operation->o_ber;

	/* count the add request */
	slapi_counter_increment(g_get_global_snmp_vars()->ops_tbl.dsAddEntryOps);

	/*
	 * Parse the add request.  It looks like this:
	 *
	 *	AddRequest := [APPLICATION 14] SEQUENCE {
	 *		name	DistinguishedName,
	 *		attrs	SEQUENCE OF SEQUENCE {
	 *			type	AttributeType,
	 *			values	SET OF AttributeValue
	 *		}
	 *	}
	 */
	/* get the name */
	{
		char *rawdn = NULL;
		Slapi_DN mysdn;
		if ( ber_scanf( ber, "{a", &rawdn ) == LBER_ERROR ) {
			slapi_ch_free_string(&rawdn);
			slapi_log_err(SLAPI_LOG_ERR, "do_add",
				"ber_scanf failed (op=Add; params=DN)\n");
			op_shared_log_error_access (pb, "ADD", "???", "decoding error");
			send_ldap_result( pb, LDAP_PROTOCOL_ERROR, NULL,
				"decoding error", 0, NULL );
			return;
		}
		/* Check if we should be performing strict validation. */
		if (config_get_dn_validate_strict()) {
			/* check that the dn is formatted correctly */
			rc = slapi_dn_syntax_check(pb, rawdn, 1);
			if (rc) { /* syntax check failed */
				op_shared_log_error_access(pb, "ADD", rawdn?rawdn:"",
										   "strict: invalid dn");
				send_ldap_result(pb, LDAP_INVALID_DN_SYNTAX, 
								 NULL, "invalid dn", 0, NULL);
				slapi_ch_free_string(&rawdn);
				return;
			}
		}
		slapi_sdn_init_dn_passin(&mysdn, rawdn);
		if (rawdn && (strlen(rawdn) > 0) &&
		    (NULL == slapi_sdn_get_dn(&mysdn))) {
			/* normalization failed */
			op_shared_log_error_access(pb, "ADD", rawdn, "invalid dn");
			send_ldap_result(pb, LDAP_INVALID_DN_SYNTAX, NULL,
			                 "invalid dn", 0, NULL);
			slapi_sdn_done(&mysdn);
			return;
		}
		e = slapi_entry_alloc();
		/* Responsibility for DN is passed to the Entry. */
		slapi_entry_init_ext(e, &mysdn, NULL);
		slapi_sdn_done(&mysdn);
	}
	slapi_log_err(SLAPI_LOG_ARGS, "do_add", "dn (%s)\n", (char *)slapi_entry_get_dn_const(e));

	/* get the attrs */
	for ( tag = ber_first_element( ber, &len, &last );
	      tag != LBER_DEFAULT && tag != LBER_END_OF_SEQORSET;
	      tag = ber_next_element( ber, &len, last ) ) {
		char *type = NULL, *normtype = NULL;
		struct berval	**vals = NULL;
		len = -1; /* reset - not used in loop */
		if ( ber_scanf( ber, "{a{V}}", &type, &vals ) == LBER_ERROR ) {
			op_shared_log_error_access (pb, "ADD", slapi_sdn_get_dn (slapi_entry_get_sdn_const(e)), "decoding error");
			send_ldap_result( pb, LDAP_PROTOCOL_ERROR, NULL,
			    "decoding error", 0, NULL );
            slapi_ch_free_string(&type);
            ber_bvecfree( vals );
			goto free_and_return;
		}

		if ( vals == NULL ) {
			slapi_log_err(SLAPI_LOG_ERR, "do_add - no values for type %s\n", type, 0, 0 );
			op_shared_log_error_access (pb, "ADD", slapi_sdn_get_dn (slapi_entry_get_sdn_const(e)), "null value");
			send_ldap_result( pb, LDAP_PROTOCOL_ERROR, NULL, NULL,
			    0, NULL );
            slapi_ch_free_string(&type);
			goto free_and_return;
		}

		normtype = slapi_attr_syntax_normalize(type);
		if ( !normtype || !*normtype ) {
			char ebuf[SLAPI_DSE_RETURNTEXT_SIZE];
			rc = LDAP_INVALID_SYNTAX;
			slapi_create_errormsg(ebuf, sizeof(ebuf), "invalid type '%s'", type);
			op_shared_log_error_access (pb, "ADD", slapi_sdn_get_dn (slapi_entry_get_sdn_const(e)), ebuf);
			send_ldap_result( pb, rc, NULL, ebuf, 0, NULL );
            slapi_ch_free_string(&type);
			slapi_ch_free( (void**)&normtype );
			ber_bvecfree( vals );
			goto free_and_return;
		}
		slapi_ch_free_string(&type);
	
       /* for now we just ignore attributes that client is not allowed
          to modify so not to break existing clients */
		if (op_shared_is_allowed_attr (normtype, pb->pb_conn->c_isreplication_session)){		
			if (( rc = slapi_entry_add_values( e, normtype, vals ))
				!= LDAP_SUCCESS ) {
				slapi_log_access( LDAP_DEBUG_STATS, 
					"conn=%" NSPRIu64 " op=%d ADD dn=\"%s\", add values for type %s failed\n",
					pb->pb_conn->c_connid, operation->o_opid,
					slapi_entry_get_dn_const(e), normtype );
				send_ldap_result( pb, rc, NULL, NULL, 0, NULL );

				slapi_ch_free( (void**)&normtype );
				ber_bvecfree( vals );
				goto free_and_return;
			}

			/* if this is uniqueid attribute, set uniqueid field of the entry */
			if (strcasecmp (normtype, SLAPI_ATTR_UNIQUEID) == 0)
			{
				e->e_uniqueid = slapi_ch_strdup (vals[0]->bv_val);
			}
			if(searchsubentry) searchsubentry=check_oc_subentry(e,vals,normtype);
		}

		slapi_ch_free( (void**)&normtype );
		ber_bvecfree( vals );
	}

	/* Ensure that created attributes are not used in the RDN. */
	if (check_rdn_for_created_attrs(e)) {
		op_shared_log_error_access (pb, "ADD", slapi_sdn_get_dn(slapi_entry_get_sdn_const(e)), "invalid DN");
		send_ldap_result( pb, LDAP_INVALID_DN_SYNTAX, NULL, "illegal attribute in RDN", 0, NULL );
		goto free_and_return;
	}

    /* len, is ber_len_t, which is uint. Can't be -1. May be better to remove (len != 0) check */
	if ( (tag != LBER_END_OF_SEQORSET) && (len != -1) ) {
		op_shared_log_error_access (pb, "ADD", slapi_sdn_get_dn (slapi_entry_get_sdn_const(e)), "decoding error");
		send_ldap_result( pb, LDAP_PROTOCOL_ERROR, NULL,
		    "decoding error", 0, NULL );
		goto free_and_return;
	}

	/*
	 * in LDAPv3 there can be optional control extensions on
	 * the end of an LDAPMessage. we need to read them in and
	 * pass them to the backend.
	 */
	if ( (err = get_ldapmessage_controls( pb, ber, NULL )) != 0 ) {
		op_shared_log_error_access (pb, "ADD", slapi_sdn_get_dn (slapi_entry_get_sdn_const(e)), 
								    "failed to decode LDAP controls");
		send_ldap_result( pb, err, NULL, NULL, 0, NULL );
		goto free_and_return;
	}

	slapi_pblock_set( pb, SLAPI_REQUESTOR_ISROOT, &operation->o_isroot );
	slapi_pblock_set( pb, SLAPI_ADD_ENTRY, e );

        if (pb->pb_conn->c_flags & CONN_FLAG_IMPORT) {
            /* this add is actually part of a bulk import -- punt */
            handle_fast_add(pb, e);
        } else {
            op_shared_add ( pb );
        }

	/* make sure that we don't free entry if it is successfully added */
	e = NULL;

free_and_return:;
	if (e)
		slapi_entry_free (e);

}
Beispiel #4
0
/* This function is called to process operation that come over external connections */
void
do_delete( Slapi_PBlock *pb )
{
	Slapi_Operation *operation;
	BerElement	*ber;
	char	    *rawdn = NULL;
	int			err = 0;

	LDAPDebug( LDAP_DEBUG_TRACE, "do_delete\n", 0, 0, 0 );
	
	slapi_pblock_get( pb, SLAPI_OPERATION, &operation);
	ber = operation->o_ber;

	/* count the delete request */
	slapi_counter_increment(g_get_global_snmp_vars()->ops_tbl.dsRemoveEntryOps);

	/*
	 * Parse the delete request.  It looks like this:
	 *
	 *	DelRequest := DistinguishedName
	 */

	if ( ber_scanf( pb->pb_op->o_ber, "a", &rawdn ) == LBER_ERROR ) {
		LDAPDebug( LDAP_DEBUG_ANY,
		    "ber_scanf failed (op=Delete; params=DN)\n", 0, 0, 0 );
		op_shared_log_error_access (pb, "DEL", "???", "decoding error");
		send_ldap_result( pb, LDAP_PROTOCOL_ERROR, NULL, NULL, 0,
		    NULL );
		goto free_and_return;
	}
	/* Check if we should be performing strict validation. */
	if (config_get_dn_validate_strict()) {
		/* check that the dn is formatted correctly */
		err = slapi_dn_syntax_check(pb, rawdn, 1);
		if (err) { /* syntax check failed */
			op_shared_log_error_access(pb, "DEL", rawdn?rawdn:"",
							"strict: invalid dn");
			send_ldap_result(pb, LDAP_INVALID_DN_SYNTAX, 
							 NULL, "invalid dn", 0, NULL);
			goto free_and_return;
		}
	}

	/*
	 * in LDAPv3 there can be optional control extensions on
	 * the end of an LDAPMessage. we need to read them in and
	 * pass them to the backend.
	 */
	if ( (err = get_ldapmessage_controls( pb, ber, NULL )) != 0 ) {
		op_shared_log_error_access (pb, "DEL", rawdn, "decoding error");
		send_ldap_result( pb, err, NULL, NULL, 0, NULL );
		goto free_and_return;
	}

	LDAPDebug1Arg( LDAP_DEBUG_ARGS, "do_delete: dn (%s)\n", rawdn );

	slapi_pblock_set( pb, SLAPI_REQUESTOR_ISROOT, &pb->pb_op->o_isroot );
	slapi_pblock_set( pb, SLAPI_ORIGINAL_TARGET, rawdn);

	op_shared_delete (pb);

free_and_return:;
	slapi_ch_free ((void**)&rawdn);
}
Beispiel #5
0
static void op_shared_delete (Slapi_PBlock *pb)
{
	char			*rawdn = NULL;
	const char		*dn = NULL;
	Slapi_Backend	*be = NULL;
	int				internal_op;
	Slapi_DN		*sdn = NULL;
	Slapi_Operation *operation;
	Slapi_Entry *referral;
	Slapi_Entry	*ecopy = NULL;
	char errorbuf[BUFSIZ];
	int				err;
	char		*proxydn = NULL;
	char		*proxystr = NULL;
	int		proxy_err = LDAP_SUCCESS;
	char		*errtext = NULL;

	slapi_pblock_get(pb, SLAPI_ORIGINAL_TARGET, &rawdn);
	slapi_pblock_get(pb, SLAPI_OPERATION, &operation);
	internal_op= operation_is_flag_set(operation, OP_FLAG_INTERNAL);

	sdn = slapi_sdn_new_dn_byval(rawdn);
	dn = slapi_sdn_get_dn(sdn);
	slapi_pblock_set(pb, SLAPI_DELETE_TARGET_SDN, (void*)sdn);
	if (rawdn && (strlen(rawdn) > 0) && (NULL == dn)) {
		/* normalization failed */
		op_shared_log_error_access(pb, "DEL", rawdn, "invalid dn");
		send_ldap_result(pb, LDAP_INVALID_DN_SYNTAX, 
		                 NULL, "invalid dn", 0, NULL);
		goto free_and_return;
	}

	/* target spec is used to decide which plugins are applicable for the operation */
	operation_set_target_spec (operation, sdn);

	/* get the proxy auth dn if the proxy auth control is present */
	proxy_err = proxyauth_get_dn(pb, &proxydn, &errtext);

	if (operation_is_flag_set(operation,OP_FLAG_ACTION_LOG_ACCESS))
	{
		if (proxydn)
		{
			proxystr = slapi_ch_smprintf(" authzid=\"%s\"", proxydn);
		}

		if (!internal_op )
		{
			slapi_log_access(LDAP_DEBUG_STATS, "conn=%" NSPRIu64 " op=%d DEL dn=\"%s\"%s\n",
							pb->pb_conn->c_connid, 
							pb->pb_op->o_opid,
							slapi_sdn_get_dn(sdn),
							proxystr ? proxystr: "");
		}
		else
		{
			slapi_log_access(LDAP_DEBUG_ARGS, "conn=%s op=%d DEL dn=\"%s\"%s\n",
							LOG_INTERNAL_OP_CON_ID,
							LOG_INTERNAL_OP_OP_ID,
							slapi_sdn_get_dn(sdn),
							proxystr ? proxystr: "");
		}
	}

	/* If we encountered an error parsing the proxy control, return an error
	 * to the client.  We do this here to ensure that we log the operation first. */
	if (proxy_err != LDAP_SUCCESS)
	{
		send_ldap_result(pb, proxy_err, NULL, errtext, 0, NULL);
		goto free_and_return;
	}

	/*
	 * We could be serving multiple database backends.  Select the
	 * appropriate one.
	 */
	if ((err = slapi_mapping_tree_select(pb, &be, &referral, errorbuf)) != LDAP_SUCCESS) {
		send_ldap_result(pb, err, NULL, errorbuf, 0, NULL);
		be = NULL;
		goto free_and_return;
	}

	if (referral)
	{
		int managedsait;

		slapi_pblock_get(pb, SLAPI_MANAGEDSAIT, &managedsait);
		if (managedsait)
		{
			send_ldap_result(pb, LDAP_UNWILLING_TO_PERFORM, NULL,
					"cannot delete referral", 0, NULL);
			slapi_entry_free(referral);
			goto free_and_return;
		}
	
		send_referrals_from_entry(pb,referral);
		slapi_entry_free(referral);
		goto free_and_return;
	}

	slapi_pblock_set(pb, SLAPI_BACKEND, be);			

	/*
	 * call the pre-delete plugins. if they succeed, call
	 * the backend delete function. then call the
	 * post-delete plugins.
	 */
	if (plugin_call_plugins(pb, internal_op ? SLAPI_PLUGIN_INTERNAL_PRE_DELETE_FN : 
							SLAPI_PLUGIN_PRE_DELETE_FN) == 0)
	{
		int	rc;

		slapi_pblock_set(pb, SLAPI_PLUGIN, be->be_database);
		set_db_default_result_handlers(pb);
		if (be->be_delete != NULL)
		{
			if ((rc = (*be->be_delete)(pb)) == 0)
			{
				/* we don't perform acl check for internal operations */
				/* Dont update aci store for remote acis              */
				if ((!internal_op) && 
					(!slapi_be_is_flag_set(be,SLAPI_BE_FLAG_REMOTE_DATA)))
					plugin_call_acl_mods_update (pb, SLAPI_OPERATION_DELETE);

				if (operation_is_flag_set(operation,OP_FLAG_ACTION_LOG_AUDIT))
					write_audit_log_entry(pb); /* Record the operation in the audit log */

				slapi_pblock_get(pb, SLAPI_ENTRY_PRE_OP, &ecopy);
				do_ps_service(ecopy, NULL, LDAP_CHANGETYPE_DELETE, 0);
			}
			else
			{
				if (rc == SLAPI_FAIL_DISKFULL)
				{
					operation_out_of_disk_space();
					goto free_and_return;
				}
			}
		}

		slapi_pblock_set(pb, SLAPI_PLUGIN_OPRETURN, &rc);
		plugin_call_plugins(pb, internal_op ? SLAPI_PLUGIN_INTERNAL_POST_DELETE_FN :
							SLAPI_PLUGIN_POST_DELETE_FN);
	}

free_and_return:
	if (be) {
		slapi_be_Unlock(be);
	}
	{
		char *coldn = NULL;
		Slapi_Entry *epre = NULL, *eparent = NULL;
		slapi_pblock_get(pb, SLAPI_ENTRY_PRE_OP, &epre);
		slapi_pblock_get(pb, SLAPI_DELETE_GLUE_PARENT_ENTRY, &eparent);
		slapi_pblock_set(pb, SLAPI_ENTRY_PRE_OP, NULL);
		slapi_pblock_set(pb, SLAPI_DELETE_GLUE_PARENT_ENTRY, NULL);
		if (epre == eparent) {
			eparent = NULL;
		}
		slapi_entry_free(epre);
		slapi_entry_free(eparent);
		slapi_pblock_get(pb, SLAPI_URP_NAMING_COLLISION_DN, &coldn);
		slapi_ch_free_string(&coldn);
	}

	slapi_pblock_get(pb, SLAPI_DELETE_TARGET_SDN, &sdn);
	slapi_sdn_free(&sdn);
	slapi_ch_free_string(&proxydn);
	slapi_ch_free_string(&proxystr);
}
Beispiel #6
0
void
do_extended( Slapi_PBlock *pb )
{
    char        *extoid = NULL, *errmsg;
    struct berval   extval = {0};
    struct slapdplugin *p = NULL;
    int     lderr, rc;
    ber_len_t   len;
    ber_tag_t   tag;
    const char  *name;

    slapi_log_err(SLAPI_LOG_TRACE, "do_extended", "->\n");

    /*
     * Parse the extended request. It looks like this:
     *
     *  ExtendedRequest := [APPLICATION 23] SEQUENCE {
     *      requestName [0] LDAPOID,
     *      requestValue    [1] OCTET STRING OPTIONAL
     *  }
     */

    if ( ber_scanf( pb->pb_op->o_ber, "{a", &extoid )
        == LBER_ERROR ) {
        slapi_log_err(SLAPI_LOG_ERR,
            "do_extended", "ber_scanf failed (op=extended; params=OID)\n");
        op_shared_log_error_access (pb, "EXT", "???", "decoding error: fail to get extension OID");
        send_ldap_result( pb, LDAP_PROTOCOL_ERROR, NULL, "decoding error", 0,
            NULL );
        goto free_and_return;
    }
    tag = ber_peek_tag(pb->pb_op->o_ber, &len);

    if (tag == LDAP_TAG_EXOP_REQ_VALUE) {
        if ( ber_scanf( pb->pb_op->o_ber, "o}", &extval ) == LBER_ERROR ) {
            op_shared_log_error_access (pb, "EXT", "???", "decoding error: fail to get extension value");
            send_ldap_result( pb, LDAP_PROTOCOL_ERROR, NULL, "decoding error", 0,
                              NULL );
            goto free_and_return;
        }
    } else {
        if ( ber_scanf( pb->pb_op->o_ber, "}") == LBER_ERROR ) {
            op_shared_log_error_access (pb, "EXT", "???", "decoding error"); 
            send_ldap_result( pb, LDAP_PROTOCOL_ERROR, NULL, "decoding error", 0,
                              NULL );
            goto free_and_return;
        }
    }
    if ( NULL == ( name = extended_op_oid2string( extoid ))) {
        slapi_log_err(SLAPI_LOG_ARGS, "do_extended", "oid (%s)\n", extoid);

        slapi_log_access( LDAP_DEBUG_STATS, "conn=%" NSPRIu64 " op=%d EXT oid=\"%s\"\n",
                pb->pb_conn->c_connid, pb->pb_op->o_opid, extoid );
    } else {
        slapi_log_err(SLAPI_LOG_ARGS, "do_extended", "oid (%s-%s)\n",
                extoid, name);

        slapi_log_access( LDAP_DEBUG_STATS,
            "conn=%" NSPRIu64 " op=%d EXT oid=\"%s\" name=\"%s\"\n",
            pb->pb_conn->c_connid, pb->pb_op->o_opid, extoid, name );
    }

    /* during a bulk import, only BULK_IMPORT_DONE is allowed! 
     * (and this is the only time it's allowed)
     */
    if (pb->pb_conn->c_flags & CONN_FLAG_IMPORT) {
        if (strcmp(extoid, EXTOP_BULK_IMPORT_DONE_OID) != 0) {
            send_ldap_result(pb, LDAP_PROTOCOL_ERROR, NULL, NULL, 0, NULL);
            goto free_and_return;
        }
        extop_handle_import_done(pb, extoid, &extval);
        goto free_and_return;
    }
    
    if (strcmp(extoid, EXTOP_BULK_IMPORT_START_OID) == 0) {
        extop_handle_import_start(pb, extoid, &extval);
        goto free_and_return;
    }

    if (strcmp(extoid, START_TLS_OID) != 0) {
        int minssf = config_get_minssf();

        /* If anonymous access is disabled and we haven't
         * authenticated yet, only allow startTLS. */
        if ((config_get_anon_access_switch() != SLAPD_ANON_ACCESS_ON) && ((pb->pb_op->o_authtype == NULL) ||
                    (strcasecmp(pb->pb_op->o_authtype, SLAPD_AUTH_NONE) == 0))) {
            send_ldap_result( pb, LDAP_INAPPROPRIATE_AUTH, NULL,
                "Anonymous access is not allowed.", 0, NULL );
            goto free_and_return;
        }

        /* If the minssf is not met, only allow startTLS. */
        if ((pb->pb_conn->c_sasl_ssf < minssf) && (pb->pb_conn->c_ssl_ssf < minssf) &&
            (pb->pb_conn->c_local_ssf < minssf)) {
            send_ldap_result( pb, LDAP_UNWILLING_TO_PERFORM, NULL,
                "Minimum SSF not met.", 0, NULL );
            goto free_and_return;
        }
    }

    /* If a password change is required, only allow the password
     * modify extended operation */
    if (!pb->pb_conn->c_isreplication_session &&
                pb->pb_conn->c_needpw && (strcmp(extoid, EXTOP_PASSWD_OID) != 0))
    {
        char *dn = NULL;
        slapi_pblock_get(pb, SLAPI_CONN_DN, &dn);

        (void)slapi_add_pwd_control ( pb, LDAP_CONTROL_PWEXPIRED, 0);
        op_shared_log_error_access (pb, "EXT", dn ? dn : "", "need new password");
        send_ldap_result( pb, LDAP_UNWILLING_TO_PERFORM, NULL, NULL, 0, NULL );

        slapi_ch_free_string(&dn);
        goto free_and_return;
    }

    /* decode the optional controls - put them in the pblock */
    if ( (lderr = get_ldapmessage_controls( pb, pb->pb_op->o_ber, NULL )) != 0 )
    {
        char *dn = NULL;
        slapi_pblock_get(pb, SLAPI_CONN_DN, &dn);

        op_shared_log_error_access (pb, "EXT", dn ? dn : "", "failed to decode LDAP controls");
        send_ldap_result( pb, lderr, NULL, NULL, 0, NULL );

        slapi_ch_free_string(&dn);
        goto free_and_return;
    }

    slapi_pblock_set( pb, SLAPI_EXT_OP_REQ_OID, extoid );
    slapi_pblock_set( pb, SLAPI_EXT_OP_REQ_VALUE, &extval );
    slapi_pblock_set( pb, SLAPI_REQUESTOR_ISROOT, &pb->pb_op->o_isroot);

    rc = plugin_determine_exop_plugins( extoid, &p );
    slapi_log_err(SLAPI_LOG_TRACE, "do_extended", "Plugin_determine_exop_plugins rc %d\n", rc);

    if (plugin_call_plugins(pb, SLAPI_PLUGIN_PRE_EXTOP_FN) != SLAPI_PLUGIN_SUCCESS) {
        goto free_and_return;
    }

    if (rc == SLAPI_PLUGIN_EXTENDEDOP && p != NULL) {
        slapi_log_err(SLAPI_LOG_TRACE, "do_extended", "Calling plugin ... \n");
        /*
         * Return values:
         *  SLAPI_PLUGIN_EXTENDED_SENT_RESULT: The result is already sent to the client. 
         *                                     There is nothing to do further.
         *  SLAPI_PLUGIN_EXTENDED_NOT_HANDLED: Unsupported extended operation
         *  LDAP codes (e.g., LDAP_SUCCESS): The result is not sent yet. Call send_ldap_result.
         */
        rc = plugin_call_exop_plugins( pb, p);

        slapi_log_err(SLAPI_LOG_TRACE, "do_extended", "Called exop, got %d \n", rc);

    } else if (rc == SLAPI_PLUGIN_BETXNEXTENDEDOP && p != NULL) {

        slapi_log_err(SLAPI_LOG_TRACE, "do_extended", "Calling betxn plugin ... \n");
        /* Look up the correct backend to use. */
        Slapi_Backend *be = plugin_extended_op_getbackend( pb, p );

        if ( be == NULL ) {
            slapi_log_err(SLAPI_LOG_ERR, "do_extended", "Plugin_extended_op_getbackend was unable to retrieve a backend!\n");
            rc = LDAP_OPERATIONS_ERROR;
        } else {
            /* We need to make a new be pb here because when you set SLAPI_BACKEND
             * you overwrite the plg parts of the pb. So if we re-use pb
             * you actually nuke the request, and everything hangs. (╯°□°)╯︵ ┻━┻
             */
            Slapi_PBlock *be_pb = NULL;
            be_pb = slapi_pblock_new();
            slapi_pblock_set(be_pb, SLAPI_BACKEND, be);

            int txn_rc = slapi_back_transaction_begin(be_pb);
            if (txn_rc) {
                slapi_log_err(SLAPI_LOG_ERR, "do_extended", "Failed to start be_txn for plugin_call_exop_plugins %d\n", txn_rc);
            } else {
                /*
                 * Return values:
                 *  SLAPI_PLUGIN_EXTENDED_SENT_RESULT: The result is already sent to the client. 
                 *                                     There is nothing to do further.
                 *  SLAPI_PLUGIN_EXTENDED_NOT_HANDLED: Unsupported extended operation
                 *  LDAP codes (e.g., LDAP_SUCCESS): The result is not sent yet. Call send_ldap_result.
                 */
                rc = plugin_call_exop_plugins( pb, p );
                slapi_log_err(SLAPI_LOG_TRACE, "do_extended", "Called betxn exop, got %d \n", rc);
                if (rc == LDAP_SUCCESS || rc == SLAPI_PLUGIN_EXTENDED_SENT_RESULT) {
                    /* commit */
                    txn_rc = slapi_back_transaction_commit(be_pb);
                    if (txn_rc == 0) {
                        slapi_log_err(SLAPI_LOG_TRACE, "do_extended", "Commit with result %d \n", txn_rc);
                    } else {
                        slapi_log_err(SLAPI_LOG_ERR, "do_extended", "Unable to commit commit with result %d \n", txn_rc);
                    }
                } else {
                    /* abort */
                    txn_rc = slapi_back_transaction_abort(be_pb);
                    slapi_log_err(SLAPI_LOG_ERR, "do_extended", "Abort with result %d \n", txn_rc);
                }
            } /* txn_rc */
            slapi_pblock_destroy(be_pb); /* Clean up after ourselves */
        } /* if be */
    }

    if (plugin_call_plugins(pb, SLAPI_PLUGIN_POST_EXTOP_FN) != SLAPI_PLUGIN_SUCCESS) {
        goto free_and_return;
    }

    if ( SLAPI_PLUGIN_EXTENDED_SENT_RESULT != rc ) {
        if ( SLAPI_PLUGIN_EXTENDED_NOT_HANDLED == rc ) {
            lderr = LDAP_PROTOCOL_ERROR;    /* no plugin handled the op */
            errmsg = "unsupported extended operation";
        } else {
            if (rc != LDAP_SUCCESS) {
                slapi_log_err(SLAPI_LOG_ERR, "do_extended", "Failed with result %d \n", rc);
            }
            errmsg = NULL;
            lderr = rc;
        }
        send_ldap_result( pb, lderr, NULL, errmsg, 0, NULL );
    }
free_and_return:
    if (extoid)
        slapi_ch_free((void **)&extoid);
    if (extval.bv_val)
        slapi_ch_free((void **)&extval.bv_val);
    return;
}