Beispiel #1
0
int
relay_back_db_open( Backend *be, ConfigReply *cr )
{
	relay_back_info		*ri = (relay_back_info *)be->be_private;

	assert( ri != NULL );

	if ( !BER_BVISNULL( &ri->ri_realsuffix ) ) {
		ri->ri_bd = select_backend( &ri->ri_realsuffix, 1 );

		/* must be there: it was during config! */
		if ( ri->ri_bd == NULL ) {
			snprintf( cr->msg, sizeof( cr->msg),
				"cannot find database "
				"of relay dn \"%s\" "
				"in \"olcRelay <dn>\"\n",
				ri->ri_realsuffix.bv_val );
			Log1( LDAP_DEBUG_ANY, LDAP_LEVEL_ERR,
				"relay_back_db_open: %s.\n", cr->msg );

			return 1;
		}

		/* inherit controls */
		AC_MEMCPY( be->bd_self->be_ctrls, ri->ri_bd->be_ctrls, sizeof( be->be_ctrls ) );

	} else {
		/* inherit all? */
		AC_MEMCPY( be->bd_self->be_ctrls, frontendDB->be_ctrls, sizeof( be->be_ctrls ) );
	}

	return 0;
}
Beispiel #2
0
int
relay_back_entry_release_rw( Operation *op, Entry *e, int rw )
{
	relay_back_info		*ri = (relay_back_info *)op->o_bd->be_private;
	BackendDB		*bd;
	int			rc = 1;

	bd = ri->ri_bd;
	if ( bd == NULL) {
		bd = select_backend( &op->o_req_ndn, 1 );
		if ( bd == NULL ) {
			return 1;
		}
	}

	if ( bd->be_release ) {
		BackendDB	*be = op->o_bd;

		op->o_bd = bd;
		rc = bd->be_release( op, e, rw );
		op->o_bd = be;
	}

	return rc;

}
Beispiel #3
0
int
relay_back_entry_get_rw( Operation *op, struct berval *ndn,
	ObjectClass *oc, AttributeDescription *at, int rw, Entry **e )
{
	relay_back_info		*ri = (relay_back_info *)op->o_bd->be_private;
	BackendDB		*bd;
	int			rc = 1;

	bd = ri->ri_bd;
	if ( bd == NULL) {
		bd = select_backend( &op->o_req_ndn, 1 );
		if ( bd == NULL ) {
			return 1;
		}
	}

	if ( bd->be_fetch ) {
		BackendDB	*be = op->o_bd;

		op->o_bd = bd;
		rc = bd->be_fetch( op, ndn, oc, at, rw, e );
		op->o_bd = be;
	}

	return rc;

}
Beispiel #4
0
idattr_id_to_dn (
    Operation	*op,
    AttributeDescription *searchAttr,
    struct berval* searchID,
    struct berval* resultDN)
{
    Operation nop = *op;
    char			filter_str[128];
    AttributeAssertion	ava = { NULL, BER_BVNULL };
    Filter			filter = {LDAP_FILTER_EQUALITY};
    SlapReply 		sreply = {REP_RESULT};
    slap_callback cb = { NULL, idattr_id_to_dn_cb, NULL, NULL };
    BackendDB	*target_bd = NULL;
    idattr_id_to_dn_t dn_result =  {0};
    int rc = 0;

    target_bd = select_backend(&op->o_req_ndn, 0);

    if (!target_bd || !target_bd->be_search)
        return LDAP_NOT_SUPPORTED;

    sreply.sr_entry = NULL;
    sreply.sr_nentries = 0;
    nop.ors_filterstr.bv_len = snprintf(filter_str, sizeof(filter_str),
                                        "(%s=%s)",searchAttr->ad_cname.bv_val, searchID->bv_val);
    filter.f_ava = &ava;
    filter.f_av_desc = searchAttr;
    filter.f_av_value = *searchID;

    nop.o_tag = LDAP_REQ_SEARCH;
    nop.o_protocol = LDAP_VERSION3;
    nop.o_callback = &cb;
    nop.o_time = slap_get_time();
    nop.o_do_not_cache = 0;
    nop.o_dn = target_bd->be_rootdn;
    nop.o_ndn = target_bd->be_rootndn;
    nop.o_bd = target_bd;

    nop.o_req_dn = target_bd->be_suffix[0];
    nop.o_req_ndn = target_bd->be_nsuffix[0];
    nop.ors_scope = LDAP_SCOPE_SUBTREE;
    nop.ors_deref = LDAP_DEREF_NEVER;
    nop.ors_slimit = SLAP_NO_LIMIT;
    nop.ors_tlimit = SLAP_NO_LIMIT;
    nop.ors_filter = &filter;
    nop.ors_filterstr.bv_val = filter_str;
    nop.ors_filterstr.bv_len = strlen(filter_str);
    nop.ors_attrs = NULL;
    nop.ors_attrsonly = 0;

    cb.sc_private = &dn_result;

    rc = nop.o_bd->be_search( &nop, &sreply );
    if (dn_result.found) {
        ber_dupbv(resultDN, &dn_result.target_dn );
    }

    return 0;
}
Beispiel #5
0
static int
slap_exop_refresh(
		Operation	*op,
		SlapReply	*rs )
{
	BackendDB		*bd = op->o_bd;

	rs->sr_err = slap_parse_refresh( op->ore_reqdata, &op->o_req_ndn, NULL,
		&rs->sr_text, op->o_tmpmemctx );
	if ( rs->sr_err != LDAP_SUCCESS ) {
		return rs->sr_err;
	}

	Log2( LDAP_DEBUG_STATS, LDAP_LEVEL_INFO,
		"%s REFRESH dn=\"%s\"\n",
		op->o_log_prefix, op->o_req_ndn.bv_val );
	op->o_req_dn = op->o_req_ndn;

	op->o_bd = select_backend( &op->o_req_ndn, 0 );
	if ( op->o_bd == NULL ) {
		send_ldap_error( op, rs, LDAP_NO_SUCH_OBJECT,
			"no global superior knowledge" );
		goto done;
	}

	if ( !SLAP_DYNAMIC( op->o_bd ) ) {
		send_ldap_error( op, rs, LDAP_UNAVAILABLE_CRITICAL_EXTENSION,
			"backend does not support dynamic directory services" );
		goto done;
	}

	rs->sr_err = backend_check_restrictions( op, rs,
		(struct berval *)&slap_EXOP_REFRESH );
	if ( rs->sr_err != LDAP_SUCCESS ) {
		goto done;
	}

	if ( op->o_bd->be_extended == NULL ) {
		send_ldap_error( op, rs, LDAP_UNAVAILABLE_CRITICAL_EXTENSION,
			"backend does not support extended operations" );
		goto done;
	}

	op->o_bd->be_extended( op, rs );

done:;
	if ( !BER_BVISNULL( &op->o_req_ndn ) ) {
		op->o_tmpfree( op->o_req_ndn.bv_val, op->o_tmpmemctx );
		BER_BVZERO( &op->o_req_ndn );
		BER_BVZERO( &op->o_req_dn );
	}
	op->o_bd = bd;

        return rs->sr_err;
}
Beispiel #6
0
/*
 * Called when controller got OP_OPEN
 * The controller passes the request to a chosen server
 */
void controller_open(int *backend_socket, int client_socket,
		     struct op_hdr get_hdr) {
  int len = -1;
  int fd = -1;  // FD
  int mode = -1;
  int name_len = 0;
  struct op_hdr put_hdr;
  int s_idx = -1;
  char path_buff[4096];

  // init
  put_hdr = get_hdr;
  mode = get_hdr.p1;
  name_len = get_hdr.p2;    // Size of file name
  printf("\tname_len: %d, mode: %d\n", name_len, mode);

  /* Read the actual data (name of the file) */
  READ_ALL(len, client_socket, path_buff, name_len);
  path_buff[name_len] = '\0';
  printf("\tfilename: %s\n", path_buff);

  // Open connection to the appropriate server
  if ((s_idx = select_backend(path_buff)) < 0) {
    printf("Requested file: %s not found\n", path_buff);
    put_hdr.op = ERR_OPEN;
    put_hdr.p1 = 0;
    WRITE_SOC(len, client_socket, &put_hdr, HDR_SIZE);
    return;
  }

    /* Connect to server */
  if ((*backend_socket = connect_to_server(server_list[s_idx].name,
					   server_port)) < 0) {
    perror("Connection to server failed");
    put_hdr.op = ERR_OPEN;
    put_hdr.p1 = errno;
    WRITE_SOC(len, client_socket, &put_hdr, HDR_SIZE);
    return;
  }

  /* Open the requested file on the backend server */
  fd = client_open(*backend_socket, path_buff, mode);

  /* Reply with the result */
  put_hdr.op = OP_OPEN;
  put_hdr.p1 = fd;
  WRITE_SOC(len, client_socket, &put_hdr, HDR_SIZE);

}
Beispiel #7
0
static int
autoca_setlocal( Operation *op, struct berval *cert, struct berval *pkey )
{
	Modifications mod[2];
	struct berval bvs[4];
	slap_callback cb = {0};
	SlapReply rs = {REP_RESULT};
	const char *text;

	mod[0].sml_numvals = 1;
	mod[0].sml_values = bvs;
	mod[0].sml_nvalues = NULL;
	mod[0].sml_desc = NULL;
	if ( slap_str2ad( "olcTLSCertificate;binary", &mod[0].sml_desc, &text ))
		return -1;
	mod[0].sml_op = LDAP_MOD_REPLACE;
	mod[0].sml_flags = SLAP_MOD_INTERNAL;
	bvs[0] = *cert;
	BER_BVZERO( &bvs[1] );
	mod[0].sml_next = &mod[1];

	mod[1].sml_numvals = 1;
	mod[1].sml_values = &bvs[2];
	mod[1].sml_nvalues = NULL;
	mod[1].sml_desc = NULL;
	if ( slap_str2ad( "olcTLSCertificateKey;binary", &mod[1].sml_desc, &text ))
		return -1;
	mod[1].sml_op = LDAP_MOD_REPLACE;
	mod[1].sml_flags = SLAP_MOD_INTERNAL;
	bvs[2] = *pkey;
	BER_BVZERO( &bvs[3] );
	mod[1].sml_next = NULL;

	cb.sc_response = slap_null_cb;
	op->o_bd = select_backend( (struct berval *)&configDN, 0 );
	if ( !op->o_bd )
		return -1;

	op->o_tag = LDAP_REQ_MODIFY;
	op->o_callback = &cb;
	op->orm_modlist = mod;
	op->orm_no_opattrs = 1;
	op->o_req_dn = configDN;
	op->o_req_ndn = configDN;
	op->o_dn = op->o_bd->be_rootdn;
	op->o_ndn = op->o_bd->be_rootndn;
	op->o_bd->be_modify( op, &rs );
	return rs.sr_err;
}
Beispiel #8
0
static void
slapi_int_set_operation_dn( Slapi_PBlock *pb )
{
	Backend			*be;
	Operation		*op = pb->pb_op;

	if ( BER_BVISNULL( &op->o_ndn ) ) {
		/* set to root DN */
		be = select_backend( &op->o_req_ndn, 1 );
		if ( be != NULL ) {
			ber_dupbv( &op->o_dn, &be->be_rootdn );
			ber_dupbv( &op->o_ndn, &be->be_rootndn );
		}
	}
}
Beispiel #9
0
idattr_is_member (
    Operation	*op,
    struct berval* groupDN,
    AttributeDescription *searchAttr,
    struct berval* searchID,
    u_int32_t * result)
{
    Operation nop = *op;
    AttributeAssertion	ava = { NULL, BER_BVNULL };
    SlapReply 		sreply = {REP_RESULT};
    slap_callback cb = { NULL, idattr_is_member_cb, NULL, NULL };
    BackendDB	*target_bd = NULL;
    idattr_ismember_t ismember =  {0};
    int rc = 0;

    target_bd = select_backend(&op->o_req_ndn, 0);

    if (!target_bd || !target_bd->be_compare)
        return LDAP_NOT_SUPPORTED;

    sreply.sr_entry = NULL;
    sreply.sr_nentries = 0;

    nop.orc_ava = &ava;
    nop.orc_ava->aa_desc = searchAttr;
    nop.orc_ava->aa_value = *searchID;

    nop.o_tag = LDAP_REQ_COMPARE;
    nop.o_protocol = LDAP_VERSION3;
    nop.o_callback = &cb;
    nop.o_time = slap_get_time();
    nop.o_do_not_cache = 0;
    nop.o_dn = target_bd->be_rootdn;
    nop.o_ndn = target_bd->be_rootndn;
    nop.o_bd = target_bd;

    nop.o_req_dn = *groupDN;
    nop.o_req_ndn = *groupDN;
    cb.sc_private = &ismember;

    rc = nop.o_bd->be_compare( &nop, &sreply );
    Debug(LDAP_DEBUG_ACL, "idattr_is_member be_compare[%d] ismember[%d]\n", rc, ismember.found, 0);
    if (ismember.found)
        *result = 1;
    else
        *result = 0;
    return 0;
}
Beispiel #10
0
/* must run as a pool thread to avoid cn=config deadlock */
static void *
autoca_setca_task( void *ctx, void *arg )
{
	Connection conn = { 0 };
	OperationBuffer opbuf;
	Operation *op;
	struct berval *cacert = arg;
	Modifications mod;
	struct berval bvs[2];
	slap_callback cb = {0};
	SlapReply rs = {REP_RESULT};
	const char *text;

	connection_fake_init( &conn, &opbuf, ctx );
	op = &opbuf.ob_op;

	mod.sml_numvals = 1;
	mod.sml_values = bvs;
	mod.sml_nvalues = NULL;
	mod.sml_desc = NULL;
	if ( slap_str2ad( "olcTLSCACertificate;binary", &mod.sml_desc, &text ))
		goto leave;
	mod.sml_op = LDAP_MOD_REPLACE;
	mod.sml_flags = SLAP_MOD_INTERNAL;
	bvs[0] = *cacert;
	BER_BVZERO( &bvs[1] );
	mod.sml_next = NULL;

	cb.sc_response = slap_null_cb;
	op->o_bd = select_backend( (struct berval *)&configDN, 0 );
	if ( !op->o_bd )
		goto leave;

	op->o_tag = LDAP_REQ_MODIFY;
	op->o_callback = &cb;
	op->orm_modlist = &mod;
	op->orm_no_opattrs = 1;
	op->o_req_dn = configDN;
	op->o_req_ndn = configDN;
	op->o_dn = op->o_bd->be_rootdn;
	op->o_ndn = op->o_bd->be_rootndn;
	op->o_bd->be_modify( op, &rs );
leave:
	ch_free( arg );
	return NULL;
}
Beispiel #11
0
static int
pblock_be_call( Slapi_PBlock *pb, int (*bep)(Operation *) )
{
	BackendDB *be_orig;
	Operation *op;
	int rc;

	PBLOCK_ASSERT_OP( pb, 0 );
	op = pb->pb_op;

	be_orig = op->o_bd;
	op->o_bd = select_backend( &op->o_req_ndn, 0 );
	rc = (*bep)( op );
	op->o_bd = be_orig;

	return rc;
}
Beispiel #12
0
static void send_page( Operation *op, SlapReply *rs, sort_op *so )
{
	TAvlnode *cur_node = so->so_tree;
	TAvlnode *next_node = NULL;
	BackendDB *be = op->o_bd;
	Entry *e;
	int rc;

	rs->sr_attrs = op->ors_attrs;

	while ( cur_node && rs->sr_nentries < so->so_page_size ) {
		sort_node *sn = cur_node->avl_data;

		if ( slapd_shutdown ) break;

		next_node = tavl_next( cur_node, TAVL_DIR_RIGHT );

		op->o_bd = select_backend( &sn->sn_dn, 0 );
		e = NULL;
		rc = be_entry_get_rw( op, &sn->sn_dn, NULL, NULL, 0, &e );

		ch_free( cur_node->avl_data );
		ber_memfree( cur_node );

		cur_node = next_node;
		so->so_nentries--;

		if ( e && rc == LDAP_SUCCESS ) {
			rs->sr_entry = e;
			rs->sr_flags = REP_ENTRY_MUSTRELEASE;
			rs->sr_err = send_search_entry( op, rs );
			if ( rs->sr_err == LDAP_UNAVAILABLE )
				break;
		}
	}

	/* Set the first entry to send for the next page */
	so->so_tree = next_node;
	if ( next_node )
		next_node->avl_left = NULL;

	op->o_bd = be;
}
Beispiel #13
0
static int
fe_entry_release_rw(
	Operation *op,
	Entry *e,
	int rw )
{
	BackendDB	*bd;
	int		rc = LDAP_NO_SUCH_OBJECT;

	bd = op->o_bd;
	op->o_bd = select_backend( &e->e_nname, 0 );
	if ( op->o_bd != NULL ) {
		if ( op->o_bd->be_release ) {
			rc = op->o_bd->be_release( op, e, rw );
		}
	}
	op->o_bd = bd;

	return rc;
}
Beispiel #14
0
static int
fe_entry_get_rw(
	Operation *op,
	struct berval *ndn,
	ObjectClass *oc,
	AttributeDescription *at,
	int rw,
	Entry **e )
{
	BackendDB	*bd;
	int		rc = LDAP_NO_SUCH_OBJECT;

	bd = op->o_bd;
	op->o_bd = select_backend( ndn, 0 );
	if ( op->o_bd != NULL ) {
		if ( op->o_bd->be_fetch ) {
			rc = op->o_bd->be_fetch( op, ndn, oc, at, rw, e );
		}
	}
	op->o_bd = bd;

	return rc;
}
Beispiel #15
0
int
relay_back_db_open( Backend *be, ConfigReply *cr )
{
	relay_back_info		*ri = (relay_back_info *)be->be_private;

	assert( ri != NULL );

	if ( !BER_BVISNULL( &ri->ri_realsuffix ) ) {
		ri->ri_bd = select_backend( &ri->ri_realsuffix, 1 );

		/* must be there: it was during config! */
		assert( ri->ri_bd != NULL );

		/* inherit controls */
		AC_MEMCPY( be->be_ctrls, ri->ri_bd->be_ctrls, sizeof( be->be_ctrls ) );

	} else {
		/* inherit all? */
		AC_MEMCPY( be->be_ctrls, frontendDB->be_ctrls, sizeof( be->be_ctrls ) );
	}

	return 0;
}
Beispiel #16
0
int
fe_op_modrdn( Operation *op, SlapReply *rs )
{
	struct berval	dest_ndn = BER_BVNULL, dest_pndn, pdn = BER_BVNULL;
	BackendDB	*op_be, *bd = op->o_bd;
	ber_slen_t	diff;
	
	if( op->o_req_ndn.bv_len == 0 ) {
		Debug( LDAP_DEBUG_ANY, "%s do_modrdn: root dse!\n",
			op->o_log_prefix, 0, 0 );
		send_ldap_error( op, rs, LDAP_UNWILLING_TO_PERFORM,
			"cannot rename the root DSE" );
		goto cleanup;

	} else if ( bvmatch( &op->o_req_ndn, &frontendDB->be_schemandn ) ) {
		Debug( LDAP_DEBUG_ANY, "%s do_modrdn: subschema subentry: %s (%ld)\n",
			op->o_log_prefix, frontendDB->be_schemandn.bv_val, (long)frontendDB->be_schemandn.bv_len );

		send_ldap_error( op, rs, LDAP_UNWILLING_TO_PERFORM,
			"cannot rename subschema subentry" );
		goto cleanup;
	}

	if( op->orr_nnewSup ) {
		dest_pndn = *op->orr_nnewSup;
	} else {
		dnParent( &op->o_req_ndn, &dest_pndn );
	}
	build_new_dn( &dest_ndn, &dest_pndn, &op->orr_nnewrdn, op->o_tmpmemctx );

	diff = (ber_slen_t) dest_ndn.bv_len - (ber_slen_t) op->o_req_ndn.bv_len;
	if ( diff > 0 ? dnIsSuffix( &dest_ndn, &op->o_req_ndn )
		: diff < 0 && dnIsSuffix( &op->o_req_ndn, &dest_ndn ) )
	{
		send_ldap_error( op, rs, LDAP_UNWILLING_TO_PERFORM,
			diff > 0 ? "cannot place an entry below itself"
			: "cannot place an entry above itself" );
		goto cleanup;
	}

	/*
	 * We could be serving multiple database backends.  Select the
	 * appropriate one, or send a referral to our "referral server"
	 * if we don't hold it.
	 */
	op->o_bd = select_backend( &op->o_req_ndn, 1 );
	if ( op->o_bd == NULL ) {
		op->o_bd = bd;
		rs->sr_ref = referral_rewrite( default_referral,
			NULL, &op->o_req_dn, LDAP_SCOPE_DEFAULT );
		if (!rs->sr_ref) rs->sr_ref = default_referral;

		if ( rs->sr_ref != NULL ) {
			rs->sr_err = LDAP_REFERRAL;
			send_ldap_result( op, rs );

			if (rs->sr_ref != default_referral) ber_bvarray_free( rs->sr_ref );
		} else {
			send_ldap_error( op, rs, LDAP_UNWILLING_TO_PERFORM,
				"no global superior knowledge" );
		}
		goto cleanup;
	}

	/* If we've got a glued backend, check the real backend */
	op_be = op->o_bd;
	if ( SLAP_GLUE_INSTANCE( op->o_bd )) {
		op->o_bd = select_backend( &op->o_req_ndn, 0 );
	}

	/* check restrictions */
	if( backend_check_restrictions( op, rs, NULL ) != LDAP_SUCCESS ) {
		send_ldap_result( op, rs );
		goto cleanup;
	}

	/* check for referrals */
	if ( backend_check_referrals( op, rs ) != LDAP_SUCCESS ) {
		goto cleanup;
	}

	/* check that destination DN is in the same backend as source DN */
	if ( select_backend( &dest_ndn, 0 ) != op->o_bd ) {
			send_ldap_error( op, rs, LDAP_AFFECTS_MULTIPLE_DSAS,
				"cannot rename between DSAs" );
			goto cleanup;
	}

	/*
	 * do the modrdn if 1 && (2 || 3)
	 * 1) there is a modrdn function implemented in this backend;
	 * 2) this backend is master for what it holds;
	 * 3) it's a replica and the dn supplied is the update_ndn.
	 */
	if ( op->o_bd->be_modrdn ) {
		/* do the update here */
		int repl_user = be_isupdate( op );
		if ( !SLAP_SINGLE_SHADOW(op->o_bd) || repl_user )
		{
			op->o_bd = op_be;
			op->o_bd->be_modrdn( op, rs );

			if ( op->o_bd->be_delete ) {
				struct berval	org_req_dn = BER_BVNULL;
				struct berval	org_req_ndn = BER_BVNULL;
				struct berval	org_dn = BER_BVNULL;
				struct berval	org_ndn = BER_BVNULL;
				int		org_managedsait;

				org_req_dn = op->o_req_dn;
				org_req_ndn = op->o_req_ndn;
				org_dn = op->o_dn;
				org_ndn = op->o_ndn;
				org_managedsait = get_manageDSAit( op );
				op->o_dn = op->o_bd->be_rootdn;
				op->o_ndn = op->o_bd->be_rootndn;
				op->o_managedsait = SLAP_CONTROL_NONCRITICAL;

				while ( rs->sr_err == LDAP_SUCCESS &&
						op->o_delete_glue_parent ) {
					op->o_delete_glue_parent = 0;
					if ( !be_issuffix( op->o_bd, &op->o_req_ndn )) {
						slap_callback cb = { NULL };
						cb.sc_response = slap_null_cb;
						dnParent( &op->o_req_ndn, &pdn );
						op->o_req_dn = pdn;
						op->o_req_ndn = pdn;
						op->o_callback = &cb;
						op->o_bd->be_delete( op, rs );
					} else {
						break;
					}
				}
				op->o_managedsait = org_managedsait;
				op->o_dn = org_dn;
				op->o_ndn = org_ndn;
				op->o_req_dn = org_req_dn;
				op->o_req_ndn = org_req_ndn;
				op->o_delete_glue_parent = 0;
			}

		} else {
			BerVarray defref = op->o_bd->be_update_refs
				? op->o_bd->be_update_refs : default_referral;

			if ( defref != NULL ) {
				rs->sr_ref = referral_rewrite( defref,
					NULL, &op->o_req_dn, LDAP_SCOPE_DEFAULT );
				if (!rs->sr_ref) rs->sr_ref = defref;

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

				if (rs->sr_ref != defref) ber_bvarray_free( rs->sr_ref );
			} else {
				send_ldap_error( op, rs, LDAP_UNWILLING_TO_PERFORM,
					"shadow context; no update referral" );
			}
		}
	} else {
		send_ldap_error( op, rs, LDAP_UNWILLING_TO_PERFORM,
			"operation not supported within namingContext" );
	}

cleanup:;
	if ( dest_ndn.bv_val != NULL )
		ber_memfree_x( dest_ndn.bv_val, op->o_tmpmemctx );
	op->o_bd = bd;
	return rs->sr_err;
}
Beispiel #17
0
int
fe_op_bind( Operation *op, SlapReply *rs )
{
	BackendDB	*bd = op->o_bd;

	/* check for inappropriate controls */
	if( get_manageDSAit( op ) == SLAP_CONTROL_CRITICAL ) {
		send_ldap_error( op, rs,
			LDAP_UNAVAILABLE_CRITICAL_EXTENSION,
			"manageDSAit control inappropriate" );
		goto cleanup;
	}

	if ( op->orb_method == LDAP_AUTH_SASL ) {
		if ( op->o_protocol < LDAP_VERSION3 ) {
			Debug( LDAP_DEBUG_ANY, "do_bind: sasl with LDAPv%ld\n",
				(unsigned long)op->o_protocol );
			send_ldap_discon( op, rs,
				LDAP_PROTOCOL_ERROR, "SASL bind requires LDAPv3" );
			rs->sr_err = SLAPD_DISCONNECT;
			goto cleanup;
		}

		if( BER_BVISNULL( &op->orb_mech ) || BER_BVISEMPTY( &op->orb_mech ) ) {
			Debug( LDAP_DEBUG_ANY,
				"do_bind: no sasl mechanism provided\n" );
			send_ldap_error( op, rs, LDAP_AUTH_METHOD_NOT_SUPPORTED,
				"no SASL mechanism provided" );
			goto cleanup;
		}

		/* check restrictions */
		if( backend_check_restrictions( op, rs, &op->orb_mech ) != LDAP_SUCCESS ) {
			send_ldap_result( op, rs );
			goto cleanup;
		}

		ldap_pvt_thread_mutex_lock( &op->o_conn->c_mutex );
		if ( op->o_conn->c_sasl_bind_in_progress ) {
			if( !bvmatch( &op->o_conn->c_sasl_bind_mech, &op->orb_mech ) ) {
				/* mechanism changed between bind steps */
				slap_sasl_reset(op->o_conn);
			}
		} else {
			ber_dupbv(&op->o_conn->c_sasl_bind_mech, &op->orb_mech);
		}

		/* Set the bindop for the benefit of in-directory SASL lookups */
		op->o_conn->c_sasl_bindop = op;

		ldap_pvt_thread_mutex_unlock( &op->o_conn->c_mutex );

		rs->sr_err = slap_sasl_bind( op, rs );

		goto cleanup;

	} else {
		/* Not SASL, cancel any in-progress bind */
		ldap_pvt_thread_mutex_lock( &op->o_conn->c_mutex );

		if ( !BER_BVISNULL( &op->o_conn->c_sasl_bind_mech ) ) {
			free( op->o_conn->c_sasl_bind_mech.bv_val );
			BER_BVZERO( &op->o_conn->c_sasl_bind_mech );
		}
		op->o_conn->c_sasl_bind_in_progress = 0;

		slap_sasl_reset( op->o_conn );
		ldap_pvt_thread_mutex_unlock( &op->o_conn->c_mutex );
	}

	if ( op->orb_method == LDAP_AUTH_SIMPLE ) {
		BER_BVSTR( &op->orb_mech, "SIMPLE" );
		/* accept "anonymous" binds */
		if ( BER_BVISEMPTY( &op->orb_cred ) || BER_BVISEMPTY( &op->o_req_ndn ) ) {
			rs->sr_err = LDAP_SUCCESS;

			if( !BER_BVISEMPTY( &op->orb_cred ) &&
				!( global_allows & SLAP_ALLOW_BIND_ANON_CRED ))
			{
				/* cred is not empty, disallow */
				rs->sr_err = LDAP_INVALID_CREDENTIALS;

			} else if ( !BER_BVISEMPTY( &op->o_req_ndn ) &&
				!( global_allows & SLAP_ALLOW_BIND_ANON_DN ))
			{
				/* DN is not empty, disallow */
				rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
				rs->sr_text =
					"unauthenticated bind (DN with no password) disallowed";

			} else if ( global_disallows & SLAP_DISALLOW_BIND_ANON ) {
				/* disallow */
				rs->sr_err = LDAP_INAPPROPRIATE_AUTH;
				rs->sr_text = "anonymous bind disallowed";

			} else {
				backend_check_restrictions( op, rs, &op->orb_mech );
			}

			/*
			 * we already forced connection to "anonymous",
			 * just need to send success
			 */
			send_ldap_result( op, rs );
			Debug( LDAP_DEBUG_TRACE, "do_bind: v%d anonymous bind\n",
				op->o_protocol );
			goto cleanup;

		} else if ( global_disallows & SLAP_DISALLOW_BIND_SIMPLE ) {
			/* disallow simple authentication */
			rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
			rs->sr_text = "unwilling to perform simple authentication";

			send_ldap_result( op, rs );
			Debug( LDAP_DEBUG_TRACE,
				"do_bind: v%d simple bind(%s) disallowed\n",
				op->o_protocol, op->o_req_ndn.bv_val );
			goto cleanup;
		}

	} else {
		rs->sr_err = LDAP_AUTH_METHOD_NOT_SUPPORTED;
		rs->sr_text = "unknown authentication method";

		send_ldap_result( op, rs );
		Debug( LDAP_DEBUG_TRACE,
			"do_bind: v%d unknown authentication method (%d)\n",
			op->o_protocol, op->orb_method );
		goto cleanup;
	}

	/*
	 * We could be serving multiple database backends.  Select the
	 * appropriate one, or send a referral to our "referral server"
	 * if we don't hold it.
	 */

	if ( (op->o_bd = select_backend( &op->o_req_ndn, 0 )) == NULL ) {
		/* don't return referral for bind requests */
		/* noSuchObject is not allowed to be returned by bind */
		rs->sr_err = LDAP_INVALID_CREDENTIALS;
		op->o_bd = bd;
		send_ldap_result( op, rs );
		goto cleanup;
	}

	/* check restrictions */
	if( backend_check_restrictions( op, rs, NULL ) != LDAP_SUCCESS ) {
		send_ldap_result( op, rs );
		goto cleanup;
	}

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

		rs->sr_err = (op->o_bd->be_bind)( op, rs );

		if ( rs->sr_err == 0 ) {
			(void)fe_op_bind_success( op, rs );

		} else if ( !BER_BVISNULL( &op->orb_edn ) ) {
			free( op->orb_edn.bv_val );
			BER_BVZERO( &op->orb_edn );
		}

	} else {
		send_ldap_error( op, rs, LDAP_UNWILLING_TO_PERFORM,
			"operation not supported within naming context" );
	}

cleanup:;
	op->o_bd = bd;
	return rs->sr_err;
}
Beispiel #18
0
static int
vernum_repair( BackendDB *be )
{
	slap_overinst *on = (slap_overinst *)be->bd_info;
	vernum_t *vn = (vernum_t *)on->on_bi.bi_private;
	void *ctx = ldap_pvt_thread_pool_context();
	Connection conn = { 0 };
	OperationBuffer opbuf;
	Operation *op;
	BackendDB db;
	slap_callback sc = { 0 };
	vernum_repair_cb_t rcb = { 0 };
	SlapReply rs = { REP_RESULT };
	vernum_mod_t *rmod;
	int nrepaired = 0;

	connection_fake_init2( &conn, &opbuf, ctx, 0 );
	op = &opbuf.ob_op;

	op->o_tag = LDAP_REQ_SEARCH;
	memset( &op->oq_search, 0, sizeof( op->oq_search ) );

	assert( !BER_BVISNULL( &be->be_nsuffix[ 0 ] ) );

	op->o_bd = select_backend( &be->be_nsuffix[ 0 ], 0 );
	assert( op->o_bd != NULL );
	assert( op->o_bd->be_nsuffix != NULL );

	op->o_req_dn = op->o_bd->be_suffix[ 0 ];
	op->o_req_ndn = op->o_bd->be_nsuffix[ 0 ];

	op->o_dn = op->o_bd->be_rootdn;
	op->o_ndn = op->o_bd->be_rootndn;

	op->ors_scope = LDAP_SCOPE_SUBTREE;
	op->ors_tlimit = SLAP_NO_LIMIT;
	op->ors_slimit = SLAP_NO_LIMIT;
	op->ors_attrs = slap_anlist_no_attrs;

	op->ors_filterstr.bv_len = STRLENOF( "(&(=*)(!(=*)))" )
		+ vn->vn_attr->ad_cname.bv_len
		+ vn->vn_vernum->ad_cname.bv_len;
	op->ors_filterstr.bv_val = op->o_tmpalloc( op->ors_filterstr.bv_len + 1, op->o_tmpmemctx );
	snprintf( op->ors_filterstr.bv_val, op->ors_filterstr.bv_len + 1,
		"(&(%s=*)(!(%s=*)))",
		vn->vn_attr->ad_cname.bv_val,
		vn->vn_vernum->ad_cname.bv_val );

	op->ors_filter = str2filter_x( op, op->ors_filterstr.bv_val );
	if ( op->ors_filter == NULL ) {
		rs.sr_err = LDAP_OTHER;
		goto done_search;
	}
	
	op->o_callback = &sc;
	sc.sc_response = vernum_repair_cb;
	sc.sc_private = &rcb;
	rcb.bd = &db;
	db = *be;
	db.bd_info = (BackendInfo *)on;

	(void)op->o_bd->bd_info->bi_op_search( op, &rs );

	op->o_tag = LDAP_REQ_MODIFY;
	sc.sc_response = slap_null_cb;
	sc.sc_private = NULL;
	memset( &op->oq_modify, 0, sizeof( req_modify_s ) );

	for ( rmod = rcb.mods; rmod != NULL; ) {
		vernum_mod_t *rnext;
		Modifications mod;
		struct berval vals[2] = { BER_BVNULL };
		SlapReply rs2 = { REP_RESULT };

		mod.sml_flags = SLAP_MOD_INTERNAL;
		mod.sml_op = LDAP_MOD_REPLACE;
		mod.sml_desc = vn->vn_vernum;
		mod.sml_type = vn->vn_vernum->ad_cname;
		mod.sml_values = vals;
		mod.sml_values[0] = val_init;
		mod.sml_nvalues = NULL;
		mod.sml_numvals = 1;
		mod.sml_next = NULL;

		op->o_req_dn = rmod->ndn;
		op->o_req_ndn = rmod->ndn;

		op->orm_modlist = &mod;

		op->o_bd->be_modify( op, &rs2 );

		slap_mods_free( op->orm_modlist->sml_next, 1 );
		if ( rs2.sr_err == LDAP_SUCCESS ) {
			Debug( LDAP_DEBUG_TRACE, "%s: vernum_repair: entry DN=\"%s\" repaired\n",
				op->o_log_prefix, rmod->ndn.bv_val, 0 );
			nrepaired++;

		} else {
			Debug( LDAP_DEBUG_ANY, "%s: vernum_repair: entry DN=\"%s\" repair failed (%d)\n",
				op->o_log_prefix, rmod->ndn.bv_val, rs2.sr_err );
		}

		rnext = rmod->next;
		op->o_tmpfree( rmod, op->o_tmpmemctx );
		rmod = rnext;
	}

done_search:;
	op->o_tmpfree( op->ors_filterstr.bv_val, op->o_tmpmemctx );
	filter_free_x( op, op->ors_filter, 1 );

	Log1( LDAP_DEBUG_STATS, LDAP_LEVEL_INFO,
		"vernum: repaired=%d\n", nrepaired );

	return 0;
}
Beispiel #19
0
int
fe_op_delete( Operation *op, SlapReply *rs )
{
	struct berval	pdn = BER_BVNULL;
	BackendDB	*op_be, *bd = op->o_bd;
	
	/*
	 * We could be serving multiple database backends.  Select the
	 * appropriate one, or send a referral to our "referral server"
	 * if we don't hold it.
	 */
	op->o_bd = select_backend( &op->o_req_ndn, 1 );
	if ( op->o_bd == NULL ) {
		op->o_bd = bd;
		rs->sr_ref = referral_rewrite( default_referral,
			NULL, &op->o_req_dn, LDAP_SCOPE_DEFAULT );

		if (!rs->sr_ref) rs->sr_ref = default_referral;
		if ( rs->sr_ref != NULL ) {
			rs->sr_err = LDAP_REFERRAL;
			send_ldap_result( op, rs );

			if (rs->sr_ref != default_referral) ber_bvarray_free( rs->sr_ref );
		} else {
			send_ldap_error( op, rs, LDAP_UNWILLING_TO_PERFORM,
				"no global superior knowledge" );
		}
		goto cleanup;
	}

	/* If we've got a glued backend, check the real backend */
	op_be = op->o_bd;
	if ( SLAP_GLUE_INSTANCE( op->o_bd )) {
		op->o_bd = select_backend( &op->o_req_ndn, 0 );
	}

	/* check restrictions */
	if( backend_check_restrictions( op, rs, NULL ) != LDAP_SUCCESS ) {
		send_ldap_result( op, rs );
		goto cleanup;
	}

	/* check for referrals */
	if( backend_check_referrals( op, rs ) != LDAP_SUCCESS ) {
		goto cleanup;
	}

	/*
	 * do the delete if 1 && (2 || 3)
	 * 1) there is a delete function implemented in this backend;
	 * 2) this backend is master for what it holds;
	 * 3) it's a replica and the dn supplied is the update_ndn.
	 */
	if ( op->o_bd->be_delete ) {
		/* do the update here */
		int repl_user = be_isupdate( op );
		if ( !SLAP_SINGLE_SHADOW(op->o_bd) || repl_user ) {
			struct berval	org_req_dn = BER_BVNULL;
			struct berval	org_req_ndn = BER_BVNULL;
			struct berval	org_dn = BER_BVNULL;
			struct berval	org_ndn = BER_BVNULL;
			int		org_managedsait;

			op->o_bd = op_be;
			op->o_bd->be_delete( op, rs );

			org_req_dn = op->o_req_dn;
			org_req_ndn = op->o_req_ndn;
			org_dn = op->o_dn;
			org_ndn = op->o_ndn;
			org_managedsait = get_manageDSAit( op );
			op->o_dn = op->o_bd->be_rootdn;
			op->o_ndn = op->o_bd->be_rootndn;
			op->o_managedsait = SLAP_CONTROL_NONCRITICAL;

			while ( rs->sr_err == LDAP_SUCCESS &&
				op->o_delete_glue_parent )
			{
				op->o_delete_glue_parent = 0;
				if ( !be_issuffix( op->o_bd, &op->o_req_ndn )) {
					slap_callback cb = { NULL, NULL, NULL, NULL };
					cb.sc_response = slap_null_cb;
					dnParent( &op->o_req_ndn, &pdn );
					op->o_req_dn = pdn;
					op->o_req_ndn = pdn;
					op->o_callback = &cb;
					op->o_bd->be_delete( op, rs );
				} else {
					break;
				}
			}

			op->o_managedsait = org_managedsait;
			op->o_dn = org_dn;
			op->o_ndn = org_ndn;
			op->o_req_dn = org_req_dn;
			op->o_req_ndn = org_req_ndn;
			op->o_delete_glue_parent = 0;

		} else {
			BerVarray defref = op->o_bd->be_update_refs
				? op->o_bd->be_update_refs : default_referral;

			if ( defref != NULL ) {
				rs->sr_ref = referral_rewrite( defref,
					NULL, &op->o_req_dn, LDAP_SCOPE_DEFAULT );
				if (!rs->sr_ref) rs->sr_ref = defref;
				rs->sr_err = LDAP_REFERRAL;
				send_ldap_result( op, rs );

				if (rs->sr_ref != defref) ber_bvarray_free( rs->sr_ref );

			} else {
				send_ldap_error( op, rs,
					LDAP_UNWILLING_TO_PERFORM,
					"shadow context; no update referral" );
			}
		}

	} else {
		send_ldap_error( op, rs, LDAP_UNWILLING_TO_PERFORM,
			"operation not supported within namingContext" );
	}

cleanup:;
	op->o_bd = bd;
	return rs->sr_err;
}
Beispiel #20
0
int passwd_extop(
	Operation *op,
	SlapReply *rs )
{
	struct berval id = {0, NULL}, hash, *rsp = NULL;
	req_pwdexop_s *qpw = &op->oq_pwdexop;
	req_extended_s qext = op->oq_extended;
	Modifications *ml;
	slap_callback cb = { NULL, slap_null_cb, NULL, NULL };
	int i, nhash;
	char **hashes, idNul;
	int rc;
	BackendDB *op_be;
	int freenewpw = 0;
	struct berval dn = BER_BVNULL, ndn = BER_BVNULL;

	assert( ber_bvcmp( &slap_EXOP_MODIFY_PASSWD, &op->ore_reqoid ) == 0 );

	if( op->o_dn.bv_len == 0 ) {
		Statslog( LDAP_DEBUG_STATS, "%s PASSMOD\n",
			op->o_log_prefix, 0, 0, 0, 0 );
		rs->sr_text = "only authenticated users may change passwords";
		return LDAP_STRONG_AUTH_REQUIRED;
	}

	qpw->rs_old.bv_len = 0;
	qpw->rs_old.bv_val = NULL;
	qpw->rs_new.bv_len = 0;
	qpw->rs_new.bv_val = NULL;
	qpw->rs_mods = NULL;
	qpw->rs_modtail = NULL;

	rs->sr_err = slap_passwd_parse( op->ore_reqdata, &id,
		&qpw->rs_old, &qpw->rs_new, &rs->sr_text );

	if ( !BER_BVISNULL( &id )) {
		idNul = id.bv_val[id.bv_len];
		id.bv_val[id.bv_len] = '\0';
	}
	if ( rs->sr_err == LDAP_SUCCESS && !BER_BVISEMPTY( &id ) ) {
		Statslog( LDAP_DEBUG_STATS, "%s PASSMOD id=\"%s\"%s%s\n",
			op->o_log_prefix, id.bv_val,
			qpw->rs_old.bv_val ? " old" : "",
			qpw->rs_new.bv_val ? " new" : "", 0 );
	} else {
		Statslog( LDAP_DEBUG_STATS, "%s PASSMOD%s%s\n",
			op->o_log_prefix,
			qpw->rs_old.bv_val ? " old" : "",
			qpw->rs_new.bv_val ? " new" : "", 0, 0 );
	}

	if ( rs->sr_err != LDAP_SUCCESS ) {
		if ( !BER_BVISNULL( &id ))
			id.bv_val[id.bv_len] = idNul;
		return rs->sr_err;
	}

	if ( !BER_BVISEMPTY( &id ) ) {
		rs->sr_err = dnPrettyNormal( NULL, &id, &dn, &ndn, op->o_tmpmemctx );
		id.bv_val[id.bv_len] = idNul;
		if ( rs->sr_err != LDAP_SUCCESS ) {
			rs->sr_text = "Invalid DN";
			rc = rs->sr_err;
			goto error_return;
		}
		op->o_req_dn = dn;
		op->o_req_ndn = ndn;
		op->o_bd = select_backend( &op->o_req_ndn, 1 );

	} else {
		ber_dupbv_x( &dn, &op->o_dn, op->o_tmpmemctx );
		ber_dupbv_x( &ndn, &op->o_ndn, op->o_tmpmemctx );
		op->o_req_dn = dn;
		op->o_req_ndn = ndn;
		ldap_pvt_thread_mutex_lock( &op->o_conn->c_mutex );
		op->o_bd = op->o_conn->c_authz_backend;
		ldap_pvt_thread_mutex_unlock( &op->o_conn->c_mutex );
	}

	if( op->o_bd == NULL ) {
		if ( qpw->rs_old.bv_val != NULL ) {
			rs->sr_text = "unwilling to verify old password";
			rc = LDAP_UNWILLING_TO_PERFORM;
			goto error_return;
		}

#ifdef HAVE_CYRUS_SASL
		rc = slap_sasl_setpass( op, rs );
#else
		rs->sr_text = "no authz backend";
		rc = LDAP_OTHER;
#endif
		goto error_return;
	}

	if ( op->o_req_ndn.bv_len == 0 ) {
		rs->sr_text = "no password is associated with the Root DSE";
		rc = LDAP_UNWILLING_TO_PERFORM;
		goto error_return;
	}

	/* If we've got a glued backend, check the real backend */
	op_be = op->o_bd;
	if ( SLAP_GLUE_INSTANCE( op->o_bd )) {
		op->o_bd = select_backend( &op->o_req_ndn, 0 );
	}

	if (backend_check_restrictions( op, rs,
			(struct berval *)&slap_EXOP_MODIFY_PASSWD ) != LDAP_SUCCESS) {
		rc = rs->sr_err;
		goto error_return;
	}

	/* check for referrals */
	if ( backend_check_referrals( op, rs ) != LDAP_SUCCESS ) {
		rc = rs->sr_err;
		goto error_return;
	}

	/* This does not apply to multi-master case */
	if(!( !SLAP_SINGLE_SHADOW( op->o_bd ) || be_isupdate( op ))) {
		/* we SHOULD return a referral in this case */
		BerVarray defref = op->o_bd->be_update_refs
			? op->o_bd->be_update_refs : default_referral; 

		if( defref != NULL ) {
			rs->sr_ref = referral_rewrite( op->o_bd->be_update_refs,
				NULL, NULL, LDAP_SCOPE_DEFAULT );
			if(rs->sr_ref) {
				rs->sr_flags |= REP_REF_MUSTBEFREED;
			} else {
				rs->sr_ref = defref;
			}
			rc = LDAP_REFERRAL;
			goto error_return;

		}

		rs->sr_text = "shadow context; no update referral";
		rc = LDAP_UNWILLING_TO_PERFORM;
		goto error_return;
	}

	/* generate a new password if none was provided */
	if ( qpw->rs_new.bv_len == 0 ) {
		slap_passwd_generate( &qpw->rs_new );
		if ( qpw->rs_new.bv_len ) {
			rsp = slap_passwd_return( &qpw->rs_new );
			freenewpw = 1;
		}
	}
	if ( qpw->rs_new.bv_len == 0 ) {
		rs->sr_text = "password generation failed";
		rc = LDAP_OTHER;
		goto error_return;
	}

	op->o_bd = op_be;

	/* Give the backend a chance to handle this itself */
	if ( op->o_bd->be_extended ) {
		rs->sr_err = op->o_bd->be_extended( op, rs );
		if ( rs->sr_err != LDAP_UNWILLING_TO_PERFORM &&
			rs->sr_err != SLAP_CB_CONTINUE )
		{
			rc = rs->sr_err;
			if ( rsp ) {
				rs->sr_rspdata = rsp;
				rsp = NULL;
			}
			goto error_return;
		}
	}

	/* The backend didn't handle it, so try it here */
	if( op->o_bd && !op->o_bd->be_modify ) {
		rs->sr_text = "operation not supported for current user";
		rc = LDAP_UNWILLING_TO_PERFORM;
		goto error_return;
	}

	if ( qpw->rs_old.bv_val != NULL ) {
		Entry *e = NULL;

		rc = be_entry_get_rw( op, &op->o_req_ndn, NULL,
			slap_schema.si_ad_userPassword, 0, &e );
		if ( rc == LDAP_SUCCESS && e ) {
			Attribute *a = attr_find( e->e_attrs,
				slap_schema.si_ad_userPassword );
			if ( a )
				rc = slap_passwd_check( op, e, a, &qpw->rs_old, &rs->sr_text );
			else
				rc = 1;
			be_entry_release_r( op, e );
			if ( rc == LDAP_SUCCESS )
				goto old_good;
		}
		rs->sr_text = "unwilling to verify old password";
		rc = LDAP_UNWILLING_TO_PERFORM;
		goto error_return;
	}

old_good:
	ml = ch_malloc( sizeof(Modifications) );
	if ( !qpw->rs_modtail ) qpw->rs_modtail = &ml->sml_next;

	if ( default_passwd_hash ) {
		for ( nhash = 0; default_passwd_hash[nhash]; nhash++ );
		hashes = default_passwd_hash;
	} else {
		nhash = 1;
		hashes = (char **)defhash;
	}
	ml->sml_numvals = nhash;
	ml->sml_values = ch_malloc( (nhash+1)*sizeof(struct berval) );
	for ( i=0; hashes[i]; i++ ) {
		slap_passwd_hash_type( &qpw->rs_new, &hash, hashes[i], &rs->sr_text );
		if ( hash.bv_len == 0 ) {
			if ( !rs->sr_text ) {
				rs->sr_text = "password hash failed";
			}
			break;
		}
		ml->sml_values[i] = hash;
	}
	ml->sml_values[i].bv_val = NULL;
	ml->sml_nvalues = NULL;
	ml->sml_desc = slap_schema.si_ad_userPassword;
	ml->sml_type = ml->sml_desc->ad_cname;
	ml->sml_op = LDAP_MOD_REPLACE;
	ml->sml_flags = 0;
	ml->sml_next = qpw->rs_mods;
	qpw->rs_mods = ml;

	if ( hashes[i] ) {
		rs->sr_err = LDAP_OTHER;

	} else {
		slap_callback *sc = op->o_callback;

		op->o_tag = LDAP_REQ_MODIFY;
		op->o_callback = &cb;
		op->orm_modlist = qpw->rs_mods;
		op->orm_no_opattrs = 0;
		
		cb.sc_private = qpw;	/* let Modify know this was pwdMod,
					 * if it cares... */

		rs->sr_err = op->o_bd->be_modify( op, rs );

		/* be_modify() might have shuffled modifications */
		qpw->rs_mods = op->orm_modlist;

		if ( rs->sr_err == LDAP_SUCCESS ) {
			rs->sr_rspdata = rsp;

		} else if ( rsp ) {
			ber_bvfree( rsp );
			rsp = NULL;
		}
		op->o_tag = LDAP_REQ_EXTENDED;
		op->o_callback = sc;
	}

	rc = rs->sr_err;
	op->oq_extended = qext;

error_return:;
	if ( qpw->rs_mods ) {
		slap_mods_free( qpw->rs_mods, 1 );
	}
	if ( freenewpw ) {
		free( qpw->rs_new.bv_val );
	}
	if ( !BER_BVISNULL( &dn ) ) {
		op->o_tmpfree( dn.bv_val, op->o_tmpmemctx );
		BER_BVZERO( &op->o_req_dn );
	}
	if ( !BER_BVISNULL( &ndn ) ) {
		op->o_tmpfree( ndn.bv_val, op->o_tmpmemctx );
		BER_BVZERO( &op->o_req_ndn );
	}

	return rc;
}
Beispiel #21
0
static int 
pblock_get( Slapi_PBlock *pb, int param, void **value ) 
{
	int rc = PBLOCK_SUCCESS;

	pblock_lock( pb );

	switch ( param ) {
	case SLAPI_OPERATION:
		*value = pb->pb_op;
		break;
	case SLAPI_OPINITIATED_TIME:
		PBLOCK_ASSERT_OP( pb, 0 );
		*((long *)value) = pb->pb_op->o_time;
		break;
	case SLAPI_OPERATION_ID:
		PBLOCK_ASSERT_OP( pb, 0 );
		*((long *)value) = pb->pb_op->o_opid;
		break;
	case SLAPI_OPERATION_TYPE:
		PBLOCK_ASSERT_OP( pb, 0 );
		*((ber_tag_t *)value) = pb->pb_op->o_tag;
		break;
	case SLAPI_OPERATION_MSGID:
		PBLOCK_ASSERT_OP( pb, 0 );
		*((long *)value) = pb->pb_op->o_msgid;
		break;
	case SLAPI_X_OPERATION_DELETE_GLUE_PARENT:
		PBLOCK_ASSERT_OP( pb, 0 );
		*((int *)value) = pb->pb_op->o_delete_glue_parent;
		break;
	case SLAPI_X_OPERATION_NO_SCHEMA_CHECK:
		PBLOCK_ASSERT_OP( pb, 0 );
		*((int *)value) = get_no_schema_check( pb->pb_op );
		break;
	case SLAPI_X_ADD_STRUCTURAL_CLASS:
		PBLOCK_ASSERT_OP( pb, 0 );

		if ( pb->pb_op->o_tag == LDAP_REQ_ADD ) {
			struct berval tmpval = BER_BVNULL;

			rc = mods_structural_class( pb->pb_op->ora_modlist,
				&tmpval, &pb->pb_rs->sr_text,
				pb->pb_textbuf, sizeof( pb->pb_textbuf ),
				pb->pb_op->o_tmpmemctx );
			*((char **)value) = tmpval.bv_val;
		} else {
			rc = PBLOCK_ERROR;
		}
		break;
	case SLAPI_X_OPERATION_NO_SUBORDINATE_GLUE:
		PBLOCK_ASSERT_OP( pb, 0 );
		*((int *)value) = pb->pb_op->o_no_subordinate_glue;
		break;
	case SLAPI_REQCONTROLS:
		PBLOCK_ASSERT_OP( pb, 0 );
		*((LDAPControl ***)value) = pb->pb_op->o_ctrls;
		break;
	case SLAPI_REQUESTOR_DN:
		PBLOCK_ASSERT_OP( pb, 0 );
		*((char **)value) = pb->pb_op->o_dn.bv_val;
		break;
	case SLAPI_MANAGEDSAIT:
		PBLOCK_ASSERT_OP( pb, 0 );
		*((int *)value) = get_manageDSAit( pb->pb_op );
		break;
	case SLAPI_X_RELAX:
		PBLOCK_ASSERT_OP( pb, 0 );
		*((int *)value) = get_relax( pb->pb_op );
		break;
	case SLAPI_BACKEND:
		PBLOCK_ASSERT_OP( pb, 0 );
		*((BackendDB **)value) = select_backend( &pb->pb_op->o_req_ndn, 0 );
		break;
	case SLAPI_BE_TYPE:
		PBLOCK_ASSERT_OP( pb, 0 );
		if ( pb->pb_op->o_bd != NULL )
			*((char **)value) = pb->pb_op->o_bd->bd_info->bi_type;
		else
			*value = NULL;
		break;
	case SLAPI_CONNECTION:
		*value = pb->pb_conn;
		break;
	case SLAPI_X_CONN_SSF:
		PBLOCK_ASSERT_OP( pb, 0 );
		*((slap_ssf_t *)value) = pb->pb_conn->c_ssf;
		break;
	case SLAPI_X_CONN_SASL_CONTEXT:
		PBLOCK_ASSERT_CONN( pb );
		if ( pb->pb_conn->c_sasl_authctx != NULL )
			*value = pb->pb_conn->c_sasl_authctx;
		else
			*value = pb->pb_conn->c_sasl_sockctx;
		break;
	case SLAPI_TARGET_DN:
		PBLOCK_ASSERT_OP( pb, 0 );
		*((char **)value) = pb->pb_op->o_req_dn.bv_val;
		break;
	case SLAPI_REQUESTOR_ISROOT:
		*((int *)value) = pblock_be_call( pb, be_isroot );
		break;
	case SLAPI_IS_REPLICATED_OPERATION:
		*((int *)value) = pblock_be_call( pb, be_slurp_update );
		break;
	case SLAPI_CONN_AUTHTYPE:
	case SLAPI_CONN_AUTHMETHOD: /* XXX should return SASL mech */
		PBLOCK_ASSERT_CONN( pb );
		*((char **)value) = pblock_get_authtype( &pb->pb_conn->c_authz,
#ifdef HAVE_TLS
							 pb->pb_conn->c_is_tls
#else
							 0
#endif
							 );
		break;
	case SLAPI_IS_INTERNAL_OPERATION:
		*((int *)value) = pb->pb_intop;
		break;
	case SLAPI_X_CONN_IS_UDP:
		PBLOCK_ASSERT_CONN( pb );
#ifdef LDAP_CONNECTIONLESS
		*((int *)value) = pb->pb_conn->c_is_udp;
#else
		*((int *)value) = 0;
#endif
		break;
	case SLAPI_CONN_ID:
		PBLOCK_ASSERT_CONN( pb );
		*((long *)value) = pb->pb_conn->c_connid;
		break;
	case SLAPI_CONN_DN:
		PBLOCK_ASSERT_CONN( pb );
#if 0
		/* This would be necessary to keep plugin compat after the fix in ITS#4158 */
		if ( pb->pb_op->o_tag == LDAP_REQ_BIND && pb->pb_rs->sr_err == LDAP_SUCCESS )
			*((char **)value) = pb->pb_op->orb_edn.bv_val;
		else
#endif
		*((char **)value) = pb->pb_conn->c_dn.bv_val;
		break;
	case SLAPI_CONN_CLIENTIP:
		PBLOCK_ASSERT_CONN( pb );
		if ( strncmp( pb->pb_conn->c_peer_name.bv_val, "IP=", 3 ) == 0 )
			*((char **)value) = &pb->pb_conn->c_peer_name.bv_val[3];
		else
			*value = NULL;
		break;
	case SLAPI_X_CONN_CLIENTPATH:
		PBLOCK_ASSERT_CONN( pb );
		if ( strncmp( pb->pb_conn->c_peer_name.bv_val, "PATH=", 3 ) == 0 )
			*((char **)value) = &pb->pb_conn->c_peer_name.bv_val[5];
		else
			*value = NULL;
		break;
	case SLAPI_CONN_SERVERIP:
		PBLOCK_ASSERT_CONN( pb );
		if ( strncmp( pb->pb_conn->c_sock_name.bv_val, "IP=", 3 ) == 0 )
			*((char **)value) = &pb->pb_conn->c_sock_name.bv_val[3];
		else
			*value = NULL;
		break;
	case SLAPI_X_CONN_SERVERPATH:
		PBLOCK_ASSERT_CONN( pb );
		if ( strncmp( pb->pb_conn->c_sock_name.bv_val, "PATH=", 3 ) == 0 )
			*((char **)value) = &pb->pb_conn->c_sock_name.bv_val[5];
		else
			*value = NULL;
		break;
	case SLAPI_RESULT_CODE:
	case SLAPI_PLUGIN_INTOP_RESULT:
		PBLOCK_ASSERT_OP( pb, 0 );
		*((int *)value) = pb->pb_rs->sr_err;
		break;
        case SLAPI_RESULT_TEXT:
		PBLOCK_ASSERT_OP( pb, 0 );
		*((const char **)value) = pb->pb_rs->sr_text;
		break;
        case SLAPI_RESULT_MATCHED:
		PBLOCK_ASSERT_OP( pb, 0 );
		*((const char **)value) = pb->pb_rs->sr_matched;
		break;
	case SLAPI_ADD_ENTRY:
		PBLOCK_ASSERT_OP( pb, 0 );
		if ( pb->pb_op->o_tag == LDAP_REQ_ADD )
			*((Slapi_Entry **)value) = pb->pb_op->ora_e;
		else
			*value = NULL;
		break;
	case SLAPI_MODIFY_MODS: {
		LDAPMod **mods = NULL;
		Modifications *ml = NULL;

		pblock_get_default( pb, param, (void **)&mods );
		if ( mods == NULL && pb->pb_intop == 0 ) {
			switch ( pb->pb_op->o_tag ) {
			case LDAP_REQ_MODIFY:
				ml = pb->pb_op->orm_modlist;
				break;
			case LDAP_REQ_MODRDN:
				ml = pb->pb_op->orr_modlist;
				break;
			default:
				rc = PBLOCK_ERROR;
				break;
			}
			if ( rc != PBLOCK_ERROR ) {
				mods = slapi_int_modifications2ldapmods( ml );
				pblock_set_default( pb, param, (void *)mods );
			}
		}
		*((LDAPMod ***)value) = mods;
		break;
	}
	case SLAPI_MODRDN_NEWRDN:
		PBLOCK_ASSERT_OP( pb, 0 );
		if ( pb->pb_op->o_tag == LDAP_REQ_MODRDN )
			*((char **)value) = pb->pb_op->orr_newrdn.bv_val;
		else
			*value = NULL;
		break;
	case SLAPI_MODRDN_NEWSUPERIOR:
		PBLOCK_ASSERT_OP( pb, 0 );
		if ( pb->pb_op->o_tag == LDAP_REQ_MODRDN && pb->pb_op->orr_newSup != NULL )
			*((char **)value) = pb->pb_op->orr_newSup->bv_val;
		else
			*value = NULL;
		break;
	case SLAPI_MODRDN_DELOLDRDN:
		PBLOCK_ASSERT_OP( pb, 0 );
		if ( pb->pb_op->o_tag == LDAP_REQ_MODRDN )
			*((int *)value) = pb->pb_op->orr_deleteoldrdn;
		else
			*((int *)value) = 0;
		break;
	case SLAPI_SEARCH_SCOPE:
		PBLOCK_ASSERT_OP( pb, 0 );
		if ( pb->pb_op->o_tag == LDAP_REQ_SEARCH )
			*((int *)value) = pb->pb_op->ors_scope;
		else
			*((int *)value) = 0;
		break;
	case SLAPI_SEARCH_DEREF:
		PBLOCK_ASSERT_OP( pb, 0 );
		if ( pb->pb_op->o_tag == LDAP_REQ_SEARCH )
			*((int *)value) = pb->pb_op->ors_deref;
		else
			*((int *)value) = 0;
		break;
	case SLAPI_SEARCH_SIZELIMIT:
		PBLOCK_ASSERT_OP( pb, 0 );
		if ( pb->pb_op->o_tag == LDAP_REQ_SEARCH )
			*((int *)value) = pb->pb_op->ors_slimit;
		else
			*((int *)value) = 0;
		break;
	case SLAPI_SEARCH_TIMELIMIT:
		PBLOCK_ASSERT_OP( pb, 0 );
		if ( pb->pb_op->o_tag == LDAP_REQ_SEARCH )
			*((int *)value) = pb->pb_op->ors_tlimit;
		else
			*((int *)value) = 0;
		break;
	case SLAPI_SEARCH_FILTER:
		PBLOCK_ASSERT_OP( pb, 0 );
		if ( pb->pb_op->o_tag == LDAP_REQ_SEARCH )
			*((Slapi_Filter **)value) = pb->pb_op->ors_filter;
		else
			*((Slapi_Filter **)value) = NULL;
		break;
	case SLAPI_SEARCH_STRFILTER:
		PBLOCK_ASSERT_OP( pb, 0 );
		if ( pb->pb_op->o_tag == LDAP_REQ_SEARCH )
			*((char **)value) = pb->pb_op->ors_filterstr.bv_val;
		else
			*((char **)value) = NULL;
		break;
	case SLAPI_SEARCH_ATTRS: {
		char **attrs = NULL;

		PBLOCK_ASSERT_OP( pb, 0 );
		if ( pb->pb_op->o_tag != LDAP_REQ_SEARCH ) {
			rc = PBLOCK_ERROR;
			break;
		}
		pblock_get_default( pb, param, (void **)&attrs );
		if ( attrs == NULL && pb->pb_intop == 0 ) {
			attrs = anlist2charray_x( pb->pb_op->ors_attrs, 0, pb->pb_op->o_tmpmemctx );
			pblock_set_default( pb, param, (void *)attrs );
		}
		*((char ***)value) = attrs;
		break;
	}
	case SLAPI_SEARCH_ATTRSONLY:
		PBLOCK_ASSERT_OP( pb, 0 );
		if ( pb->pb_op->o_tag == LDAP_REQ_SEARCH )
			*((int *)value) = pb->pb_op->ors_attrsonly;
		else
			*((int *)value) = 0;
		break;
	case SLAPI_SEARCH_RESULT_ENTRY:
		PBLOCK_ASSERT_OP( pb, 0 );
		*((Slapi_Entry **)value) = pb->pb_rs->sr_entry;
		break;
	case SLAPI_BIND_RET_SASLCREDS:
		PBLOCK_ASSERT_OP( pb, 0 );
		*((struct berval **)value) = pb->pb_rs->sr_sasldata;
		break;
	case SLAPI_EXT_OP_REQ_OID:
		*((const char **)value) = pb->pb_op->ore_reqoid.bv_val;
		break;
	case SLAPI_EXT_OP_REQ_VALUE:
		*((struct berval **)value) = pb->pb_op->ore_reqdata;
		break;
	case SLAPI_EXT_OP_RET_OID:
		PBLOCK_ASSERT_OP( pb, 0 );
		*((const char **)value) = pb->pb_rs->sr_rspoid;
		break;
	case SLAPI_EXT_OP_RET_VALUE:
		PBLOCK_ASSERT_OP( pb, 0 );
		*((struct berval **)value) = pb->pb_rs->sr_rspdata;
		break;
	case SLAPI_BIND_METHOD:
		if ( pb->pb_op->o_tag == LDAP_REQ_BIND )
			*((int *)value) = pb->pb_op->orb_method;
		else
			*((int *)value) = 0;
		break;
	case SLAPI_BIND_CREDENTIALS:
		if ( pb->pb_op->o_tag == LDAP_REQ_BIND )
			*((struct berval **)value) = &pb->pb_op->orb_cred;
		else
			*value = NULL;
		break;
	case SLAPI_COMPARE_TYPE:
		if ( pb->pb_op->o_tag == LDAP_REQ_COMPARE )
			*((char **)value) = pb->pb_op->orc_ava->aa_desc->ad_cname.bv_val;
		else
			*value = NULL;
		break;
	case SLAPI_COMPARE_VALUE:
		if ( pb->pb_op->o_tag == LDAP_REQ_COMPARE )
			*((struct berval **)value) = &pb->pb_op->orc_ava->aa_value;
		else
			*value = NULL;
		break;
	case SLAPI_ABANDON_MSGID:
		if ( pb->pb_op->o_tag == LDAP_REQ_ABANDON )
			*((int *)value) = pb->pb_op->orn_msgid;
		else
			*((int *)value) = 0;
		break;
	default:
		rc = pblock_get_default( pb, param, value );
		break;
	}

	pblock_unlock( pb );

	return rc;
}
Beispiel #22
0
static int
slapi_over_acl_group(
	Operation		*op,
	Entry			*target,
	struct berval		*gr_ndn,
	struct berval		*op_ndn,
	ObjectClass		*group_oc,
	AttributeDescription	*group_at )
{
	Slapi_Entry		*e;
	int			rc;
	Slapi_PBlock		*pb;
	BackendDB		*be = op->o_bd;
	GroupAssertion		*g;
	SlapReply		rs = { REP_RESULT };

	op->o_bd = select_backend( gr_ndn, 0 );

	for ( g = op->o_groups; g; g = g->ga_next ) {
		if ( g->ga_be != op->o_bd || g->ga_oc != group_oc ||
			g->ga_at != group_at || g->ga_len != gr_ndn->bv_len )
		{
			continue;
		}
		if ( strcmp( g->ga_ndn, gr_ndn->bv_val ) == 0 ) {
			break;
		}
	}
	if ( g != NULL ) {
		rc = g->ga_res;
		goto done;
	}

	if ( target != NULL && dn_match( &target->e_nname, gr_ndn ) ) {
		e = target;
		rc = 0;
	} else {
		rc = be_entry_get_rw( op, gr_ndn, group_oc, group_at, 0, &e );
	}
	if ( e != NULL ) {
		int			internal_op;
		slap_callback		cb;

		internal_op = slapi_op_internal_p( op, &rs, &cb );

		cb.sc_response = NULL;
		cb.sc_cleanup = NULL;

		pb = SLAPI_OPERATION_PBLOCK( op );

		slapi_pblock_set( pb, SLAPI_X_GROUP_ENTRY,        (void *)e );
		slapi_pblock_set( pb, SLAPI_X_GROUP_OPERATION_DN, (void *)op_ndn->bv_val );
		slapi_pblock_set( pb, SLAPI_X_GROUP_ATTRIBUTE,    (void *)group_at->ad_cname.bv_val );
		slapi_pblock_set( pb, SLAPI_X_GROUP_TARGET_ENTRY, (void *)target );

		rc = slapi_over_call_plugins( pb, SLAPI_X_PLUGIN_PRE_GROUP_FN );
		if ( rc >= 0 ) /* 1 means no plugins called */
			rc = SLAP_CB_CONTINUE;
		else
			rc = pb->pb_rs->sr_err;

		slapi_pblock_delete_param( pb, SLAPI_X_GROUP_ENTRY );
		slapi_pblock_delete_param( pb, SLAPI_X_GROUP_OPERATION_DN );
		slapi_pblock_delete_param( pb, SLAPI_X_GROUP_ATTRIBUTE );
		slapi_pblock_delete_param( pb, SLAPI_X_GROUP_TARGET_ENTRY );

		if ( !internal_op )
			slapi_pblock_destroy( pb );

		if ( e != target ) {
			be_entry_release_r( op, e );
		}

		op->o_callback = cb.sc_next;
	} else {
		rc = LDAP_NO_SUCH_OBJECT; /* return SLAP_CB_CONTINUE for correctness? */
	}

	if ( op->o_tag != LDAP_REQ_BIND && !op->o_do_not_cache &&
	     rc != SLAP_CB_CONTINUE ) {
		g = op->o_tmpalloc( sizeof( GroupAssertion ) + gr_ndn->bv_len,
			op->o_tmpmemctx );
		g->ga_be = op->o_bd;
		g->ga_oc = group_oc;
		g->ga_at = group_at;
		g->ga_res = rc;
		g->ga_len = gr_ndn->bv_len;
		strcpy( g->ga_ndn, gr_ndn->bv_val );
		g->ga_next = op->o_groups;
		op->o_groups = g;
	}
	/*
	 * XXX don't call POST_GROUP_FN, I have no idea what the point of
	 * that plugin function was anyway
	 */
done:
	op->o_bd = be;
	return rc;
}
Beispiel #23
0
int
fe_op_compare( Operation *op, SlapReply *rs )
{
	Entry			*entry = NULL;
	AttributeAssertion	*ava = op->orc_ava;
	BackendDB		*bd = op->o_bd;

	if( strcasecmp( op->o_req_ndn.bv_val, LDAP_ROOT_DSE ) == 0 ) {
		if( backend_check_restrictions( op, rs, NULL ) != LDAP_SUCCESS ) {
			send_ldap_result( op, rs );
			goto cleanup;
		}

		rs->sr_err = root_dse_info( op->o_conn, &entry, &rs->sr_text );
		if( rs->sr_err != LDAP_SUCCESS ) {
			send_ldap_result( op, rs );
			goto cleanup;
		}

	} else if ( bvmatch( &op->o_req_ndn, &frontendDB->be_schemandn ) ) {
		if( backend_check_restrictions( op, rs, NULL ) != LDAP_SUCCESS ) {
			send_ldap_result( op, rs );
			rs->sr_err = 0;
			goto cleanup;
		}

		rs->sr_err = schema_info( &entry, &rs->sr_text );
		if( rs->sr_err != LDAP_SUCCESS ) {
			send_ldap_result( op, rs );
			rs->sr_err = 0;
			goto cleanup;
		}
	}

	if( entry ) {
		rs->sr_err = slap_compare_entry( op, entry, ava );
		entry_free( entry );

		send_ldap_result( op, rs );

		if( rs->sr_err == LDAP_COMPARE_TRUE ||
			rs->sr_err == LDAP_COMPARE_FALSE )
		{
			rs->sr_err = LDAP_SUCCESS;
		}

		goto cleanup;
	}

	/*
	 * We could be serving multiple database backends.  Select the
	 * appropriate one, or send a referral to our "referral server"
	 * if we don't hold it.
	 */
	op->o_bd = select_backend( &op->o_req_ndn, 0 );
	if ( op->o_bd == NULL ) {
		rs->sr_ref = referral_rewrite( default_referral,
			NULL, &op->o_req_dn, LDAP_SCOPE_DEFAULT );

		rs->sr_err = LDAP_REFERRAL;
		if (!rs->sr_ref) rs->sr_ref = default_referral;
		op->o_bd = bd;
		send_ldap_result( op, rs );

		if (rs->sr_ref != default_referral) ber_bvarray_free( rs->sr_ref );
		rs->sr_err = 0;
		goto cleanup;
	}

	/* check restrictions */
	if( backend_check_restrictions( op, rs, NULL ) != LDAP_SUCCESS ) {
		send_ldap_result( op, rs );
		goto cleanup;
	}

	/* check for referrals */
	if( backend_check_referrals( op, rs ) != LDAP_SUCCESS ) {
		goto cleanup;
	}

	if ( SLAP_SHADOW(op->o_bd) && get_dontUseCopy(op) ) {
		/* don't use shadow copy */
		send_ldap_error( op, rs, LDAP_UNWILLING_TO_PERFORM,
			"copy not used" );

	} else if ( ava->aa_desc == slap_schema.si_ad_entryDN ) {
		send_ldap_error( op, rs, LDAP_UNWILLING_TO_PERFORM,
			"entryDN compare not supported" );

	} else if ( ava->aa_desc == slap_schema.si_ad_subschemaSubentry ) {
		send_ldap_error( op, rs, LDAP_UNWILLING_TO_PERFORM,
			"subschemaSubentry compare not supported" );

#ifndef SLAP_COMPARE_IN_FRONTEND
	} else if ( ava->aa_desc == slap_schema.si_ad_hasSubordinates
		&& op->o_bd->be_has_subordinates )
	{
		int	rc, hasSubordinates = LDAP_SUCCESS;

		rc = be_entry_get_rw( op, &op->o_req_ndn, NULL, NULL, 0, &entry );
		if ( rc == 0 && entry ) {
			if ( ! access_allowed( op, entry,
				ava->aa_desc, &ava->aa_value, ACL_COMPARE, NULL ) )
			{	
				rc = rs->sr_err = LDAP_INSUFFICIENT_ACCESS;
				
			} else {
				rc = rs->sr_err = op->o_bd->be_has_subordinates( op,
						entry, &hasSubordinates );
				be_entry_release_r( op, entry );
			}
		}

		if ( rc == 0 ) {
			int	asserted;

			asserted = bvmatch( &ava->aa_value, &slap_true_bv )
				? LDAP_COMPARE_TRUE : LDAP_COMPARE_FALSE;
			if ( hasSubordinates == asserted ) {
				rs->sr_err = LDAP_COMPARE_TRUE;

			} else {
				rs->sr_err = LDAP_COMPARE_FALSE;
			}

		} else {
			/* return error only if "disclose"
			 * is granted on the object */
			if ( backend_access( op, NULL, &op->o_req_ndn,
					slap_schema.si_ad_entry,
					NULL, ACL_DISCLOSE, NULL ) == LDAP_INSUFFICIENT_ACCESS )
			{
				rs->sr_err = LDAP_NO_SUCH_OBJECT;
			}
		}

		send_ldap_result( op, rs );

		if ( rc == 0 ) {
			rs->sr_err = LDAP_SUCCESS;
		}

	} else if ( op->o_bd->be_compare ) {
		rs->sr_err = op->o_bd->be_compare( op, rs );

#endif /* ! SLAP_COMPARE_IN_FRONTEND */
	} else {
		rs->sr_err = SLAP_CB_CONTINUE;
	}

	if ( rs->sr_err == SLAP_CB_CONTINUE ) {
		/* do our best to compare that AVA
		 * 
		 * NOTE: this code is used only
		 * if SLAP_COMPARE_IN_FRONTEND 
		 * is #define'd (it's not by default)
		 * or if op->o_bd->be_compare is NULL.
		 * 
		 * FIXME: one potential issue is that
		 * if SLAP_COMPARE_IN_FRONTEND overlays
		 * are not executed for compare. */
		BerVarray	vals = NULL;
		int		rc = LDAP_OTHER;

		rs->sr_err = backend_attribute( op, NULL, &op->o_req_ndn,
				ava->aa_desc, &vals, ACL_COMPARE );
		switch ( rs->sr_err ) {
		default:
			/* return error only if "disclose"
			 * is granted on the object */
			if ( backend_access( op, NULL, &op->o_req_ndn,
					slap_schema.si_ad_entry,
					NULL, ACL_DISCLOSE, NULL )
					== LDAP_INSUFFICIENT_ACCESS )
			{
				rs->sr_err = LDAP_NO_SUCH_OBJECT;
			}
			break;

		case LDAP_SUCCESS:
			if ( value_find_ex( op->oq_compare.rs_ava->aa_desc,
				SLAP_MR_ATTRIBUTE_VALUE_NORMALIZED_MATCH |
					SLAP_MR_ASSERTED_VALUE_NORMALIZED_MATCH,
				vals, &ava->aa_value, op->o_tmpmemctx ) == 0 )
			{
				rs->sr_err = LDAP_COMPARE_TRUE;
				break;

			} else {
				rs->sr_err = LDAP_COMPARE_FALSE;
			}
			rc = LDAP_SUCCESS;
			break;
		}

		send_ldap_result( op, rs );

		if ( rc == 0 ) {
			rs->sr_err = LDAP_SUCCESS;
		}
		
		if ( vals ) {
			ber_bvarray_free_x( vals, op->o_tmpmemctx );
		}
	}

cleanup:;
	op->o_bd = bd;
	return rs->sr_err;
}
Beispiel #24
0
static int
dynlist_prepare_entry( Operation *op, SlapReply *rs, dynlist_info_t *dli )
{
	Attribute	*a, *id = NULL;
	slap_callback	cb = { 0 };
	Operation	o = *op;
	struct berval	*url;
	Entry		*e;
	int		opattrs,
			userattrs;
	dynlist_sc_t	dlc = { 0 };
	dynlist_map_t	*dlm;

	a = attrs_find( rs->sr_entry->e_attrs, dli->dli_ad );
	if ( a == NULL ) {
		/* FIXME: error? */
		return SLAP_CB_CONTINUE;
	}

	opattrs = SLAP_OPATTRS( rs->sr_attr_flags );
	userattrs = SLAP_USERATTRS( rs->sr_attr_flags );

	/* Don't generate member list if it wasn't requested */
	for ( dlm = dli->dli_dlm; dlm; dlm = dlm->dlm_next ) {
		AttributeDescription *ad = dlm->dlm_mapped_ad ? dlm->dlm_mapped_ad : dlm->dlm_member_ad;
		if ( userattrs || ad_inlist( ad, rs->sr_attrs ) ) 
			break;
	}
	if ( dli->dli_dlm && !dlm )
		return SLAP_CB_CONTINUE;

	if ( ad_dgIdentity && ( id = attrs_find( rs->sr_entry->e_attrs, ad_dgIdentity ))) {
		Attribute *authz = NULL;

		/* if not rootdn and dgAuthz is present,
		 * check if user can be authorized as dgIdentity */
		if ( ad_dgAuthz && !BER_BVISEMPTY( &id->a_nvals[0] ) && !be_isroot( op )
			&& ( authz = attrs_find( rs->sr_entry->e_attrs, ad_dgAuthz ) ) )
		{
			if ( slap_sasl_matches( op, authz->a_nvals,
				&o.o_ndn, &o.o_ndn ) != LDAP_SUCCESS )
			{
				return SLAP_CB_CONTINUE;
			}
		}

		o.o_dn = id->a_vals[0];
		o.o_ndn = id->a_nvals[0];
		o.o_groups = NULL;
	}

	e = rs->sr_entry;
	/* ensure e is modifiable, but do not replace
	 * sr_entry yet since we have pointers into it */
	if ( !( rs->sr_flags & REP_ENTRY_MODIFIABLE ) ) {
		e = entry_dup( rs->sr_entry );
	}

	dlc.dlc_e = e;
	dlc.dlc_dli = dli;
	cb.sc_private = &dlc;
	cb.sc_response = dynlist_sc_update;

	o.o_callback = &cb;
	o.ors_deref = LDAP_DEREF_NEVER;
	o.ors_limit = NULL;
	o.ors_tlimit = SLAP_NO_LIMIT;
	o.ors_slimit = SLAP_NO_LIMIT;

	for ( url = a->a_nvals; !BER_BVISNULL( url ); url++ ) {
		LDAPURLDesc	*lud = NULL;
		int		i, j;
		struct berval	dn;
		int		rc;

		BER_BVZERO( &o.o_req_dn );
		BER_BVZERO( &o.o_req_ndn );
		o.ors_filter = NULL;
		o.ors_attrs = NULL;
		BER_BVZERO( &o.ors_filterstr );

		if ( ldap_url_parse( url->bv_val, &lud ) != LDAP_URL_SUCCESS ) {
			/* FIXME: error? */
			continue;
		}

		if ( lud->lud_host != NULL ) {
			/* FIXME: host not allowed; reject as illegal? */
			Debug( LDAP_DEBUG_ANY, "dynlist_prepare_entry(\"%s\"): "
				"illegal URI \"%s\"\n",
				e->e_name.bv_val, url->bv_val, 0 );
			goto cleanup;
		}

		if ( lud->lud_dn == NULL ) {
			/* note that an empty base is not honored in terms
			 * of defaultSearchBase, because select_backend()
			 * is not aware of the defaultSearchBase option;
			 * this can be useful in case of a database serving
			 * the empty suffix */
			BER_BVSTR( &dn, "" );

		} else {
			ber_str2bv( lud->lud_dn, 0, 0, &dn );
		}
		rc = dnPrettyNormal( NULL, &dn, &o.o_req_dn, &o.o_req_ndn, op->o_tmpmemctx );
		if ( rc != LDAP_SUCCESS ) {
			/* FIXME: error? */
			goto cleanup;
		}
		o.ors_scope = lud->lud_scope;

		for ( dlm = dli->dli_dlm; dlm; dlm = dlm->dlm_next ) {
			if ( dlm->dlm_mapped_ad != NULL ) {
				break;
			}
		}

		if ( dli->dli_dlm && !dlm ) {
			/* if ( lud->lud_attrs != NULL ),
			 * the URL should be ignored */
			o.ors_attrs = slap_anlist_no_attrs;

		} else if ( lud->lud_attrs == NULL ) {
			o.ors_attrs = rs->sr_attrs;

		} else {
			for ( i = 0; lud->lud_attrs[i]; i++)
				/* just count */ ;

			o.ors_attrs = op->o_tmpcalloc( i + 1, sizeof( AttributeName ), op->o_tmpmemctx );
			for ( i = 0, j = 0; lud->lud_attrs[i]; i++) {
				const char	*text = NULL;
	
				ber_str2bv( lud->lud_attrs[i], 0, 0, &o.ors_attrs[j].an_name );
				o.ors_attrs[j].an_desc = NULL;
				(void)slap_bv2ad( &o.ors_attrs[j].an_name, &o.ors_attrs[j].an_desc, &text );
				/* FIXME: ignore errors... */

				if ( rs->sr_attrs == NULL ) {
					if ( o.ors_attrs[j].an_desc != NULL &&
							is_at_operational( o.ors_attrs[j].an_desc->ad_type ) )
					{
						continue;
					}

				} else {
					if ( o.ors_attrs[j].an_desc != NULL &&
							is_at_operational( o.ors_attrs[j].an_desc->ad_type ) )
					{
						if ( !opattrs ) {
							continue;
						}

						if ( !ad_inlist( o.ors_attrs[j].an_desc, rs->sr_attrs ) ) {
							/* lookup if mapped -- linear search,
							 * not very efficient unless list
							 * is very short */
							for ( dlm = dli->dli_dlm; dlm; dlm = dlm->dlm_next ) {
								if ( dlm->dlm_member_ad == o.ors_attrs[j].an_desc ) {
									break;
								}
							}

							if ( dlm == NULL ) {
								continue;
							}
						}

					} else {
						if ( !userattrs && 
								o.ors_attrs[j].an_desc != NULL &&
								!ad_inlist( o.ors_attrs[j].an_desc, rs->sr_attrs ) )
						{
							/* lookup if mapped -- linear search,
							 * not very efficient unless list
							 * is very short */
							for ( dlm = dli->dli_dlm; dlm; dlm = dlm->dlm_next ) {
								if ( dlm->dlm_member_ad == o.ors_attrs[j].an_desc ) {
									break;
								}
							}

							if ( dlm == NULL ) {
								continue;
							}
						}
					}
				}

				j++;
			}

			if ( j == 0 ) {
				goto cleanup;
			}
		
			BER_BVZERO( &o.ors_attrs[j].an_name );
		}

		if ( lud->lud_filter == NULL ) {
			ber_dupbv_x( &o.ors_filterstr,
					&dli->dli_default_filter, op->o_tmpmemctx );

		} else {
			struct berval	flt;
			ber_str2bv( lud->lud_filter, 0, 0, &flt );
			if ( dynlist_make_filter( op, rs->sr_entry, url->bv_val, &flt, &o.ors_filterstr ) ) {
				/* error */
				goto cleanup;
			}
		}
		o.ors_filter = str2filter_x( op, o.ors_filterstr.bv_val );
		if ( o.ors_filter == NULL ) {
			goto cleanup;
		}
		
		o.o_bd = select_backend( &o.o_req_ndn, 1 );
		if ( o.o_bd && o.o_bd->be_search ) {
			SlapReply	r = { REP_SEARCH };
			r.sr_attr_flags = slap_attr_flags( o.ors_attrs );
			(void)o.o_bd->be_search( &o, &r );
		}

cleanup:;
		if ( id ) {
			slap_op_groups_free( &o );
		}
		if ( o.ors_filter ) {
			filter_free_x( &o, o.ors_filter, 1 );
		}
		if ( o.ors_attrs && o.ors_attrs != rs->sr_attrs
				&& o.ors_attrs != slap_anlist_no_attrs )
		{
			op->o_tmpfree( o.ors_attrs, op->o_tmpmemctx );
		}
		if ( !BER_BVISNULL( &o.o_req_dn ) ) {
			op->o_tmpfree( o.o_req_dn.bv_val, op->o_tmpmemctx );
		}
		if ( !BER_BVISNULL( &o.o_req_ndn ) ) {
			op->o_tmpfree( o.o_req_ndn.bv_val, op->o_tmpmemctx );
		}
		assert( BER_BVISNULL( &o.ors_filterstr )
			|| o.ors_filterstr.bv_val != lud->lud_filter );
		op->o_tmpfree( o.ors_filterstr.bv_val, op->o_tmpmemctx );
		ldap_free_urldesc( lud );
	}

	if ( e != rs->sr_entry ) {
		rs_replace_entry( op, rs, (slap_overinst *)op->o_bd->bd_info, e );
		rs->sr_flags |= REP_ENTRY_MODIFIABLE | REP_ENTRY_MUSTBEFREED;
	}

	return SLAP_CB_CONTINUE;
}
Beispiel #25
0
int
fe_op_modify( Operation *op, SlapReply *rs )
{
	BackendDB	*op_be, *bd = op->o_bd;
	char		textbuf[ SLAP_TEXT_BUFLEN ];
	size_t		textlen = sizeof( textbuf );
	
	if ( BER_BVISEMPTY( &op->o_req_ndn ) ) {
		Debug( LDAP_DEBUG_ANY, "%s do_modify: root dse!\n",
			op->o_log_prefix, 0, 0 );
		send_ldap_error( op, rs, LDAP_UNWILLING_TO_PERFORM,
			"modify upon the root DSE not supported" );
		goto cleanup;

	} else if ( bvmatch( &op->o_req_ndn, &frontendDB->be_schemandn ) ) {
		Debug( LDAP_DEBUG_ANY, "%s do_modify: subschema subentry!\n",
			op->o_log_prefix, 0, 0 );
		send_ldap_error( op, rs, LDAP_UNWILLING_TO_PERFORM,
			"modification of subschema subentry not supported" );
		goto cleanup;
	}

	/*
	 * We could be serving multiple database backends.  Select the
	 * appropriate one, or send a referral to our "referral server"
	 * if we don't hold it.
	 */
	op->o_bd = select_backend( &op->o_req_ndn, 1 );
	if ( op->o_bd == NULL ) {
		op->o_bd = bd;
		rs->sr_ref = referral_rewrite( default_referral,
			NULL, &op->o_req_dn, LDAP_SCOPE_DEFAULT );
		if ( !rs->sr_ref ) {
			rs->sr_ref = default_referral;
		}

		if ( rs->sr_ref != NULL ) {
			rs->sr_err = LDAP_REFERRAL;
			send_ldap_result( op, rs );

			if ( rs->sr_ref != default_referral ) {
				ber_bvarray_free( rs->sr_ref );
			}

		} else {
			send_ldap_error( op, rs, LDAP_UNWILLING_TO_PERFORM,
				"no global superior knowledge" );
		}
		goto cleanup;
	}

	/* If we've got a glued backend, check the real backend */
	op_be = op->o_bd;
	if ( SLAP_GLUE_INSTANCE( op->o_bd )) {
		op->o_bd = select_backend( &op->o_req_ndn, 0 );
	}

	/* check restrictions */
	if ( backend_check_restrictions( op, rs, NULL ) != LDAP_SUCCESS ) {
		send_ldap_result( op, rs );
		goto cleanup;
	}

	/* check for referrals */
	if ( backend_check_referrals( op, rs ) != LDAP_SUCCESS ) {
		goto cleanup;
	}

	rs->sr_err = slap_mods_obsolete_check( op, op->orm_modlist,
		&rs->sr_text, textbuf, textlen );
	if ( rs->sr_err != LDAP_SUCCESS ) {
		send_ldap_result( op, rs );
		goto cleanup;
	}

	/* check for modify/increment support */
	if ( op->orm_increment && !SLAP_INCREMENT( op->o_bd ) ) {
		send_ldap_error( op, rs, LDAP_UNWILLING_TO_PERFORM,
			"modify/increment not supported in context" );
		goto cleanup;
	}

	/*
	 * do the modify if 1 && (2 || 3)
	 * 1) there is a modify function implemented in this backend;
	 * 2) this backend is master for what it holds;
	 * 3) it's a replica and the dn supplied is the update_ndn.
	 */
	if ( op->o_bd->be_modify ) {
		/* do the update here */
		int repl_user = be_isupdate( op );

		/*
		 * Multimaster slapd does not have to check for replicator dn
		 * because it accepts each modify request
		 */
		if ( !SLAP_SINGLE_SHADOW(op->o_bd) || repl_user ) {
			int update = !BER_BVISEMPTY( &op->o_bd->be_update_ndn );

			op->o_bd = op_be;

			if ( !update ) {
				rs->sr_err = slap_mods_no_user_mod_check( op, op->orm_modlist,
					&rs->sr_text, textbuf, textlen );
				if ( rs->sr_err != LDAP_SUCCESS ) {
					send_ldap_result( op, rs );
					goto cleanup;
				}
			}
			op->o_bd->be_modify( op, rs );

		} else { /* send a referral */
			BerVarray defref = op->o_bd->be_update_refs
				? op->o_bd->be_update_refs : default_referral;
			if ( defref != NULL ) {
				rs->sr_ref = referral_rewrite( defref,
					NULL, &op->o_req_dn,
					LDAP_SCOPE_DEFAULT );
				if ( rs->sr_ref == NULL ) {
					/* FIXME: must duplicate, because
					 * overlays may muck with it */
					rs->sr_ref = defref;
				}
				rs->sr_err = LDAP_REFERRAL;
				send_ldap_result( op, rs );
				if ( rs->sr_ref != defref ) {
					ber_bvarray_free( rs->sr_ref );
				}

			} else {
				send_ldap_error( op, rs, LDAP_UNWILLING_TO_PERFORM,
					"shadow context; no update referral" );
			}
		}

	} else {
		send_ldap_error( op, rs, LDAP_UNWILLING_TO_PERFORM,
		    "operation not supported within namingContext" );
	}

cleanup:;
	op->o_bd = bd;
	return rs->sr_err;
}
Beispiel #26
0
static void process_read_frontend(struct conn_context *ctx)
{
	int ep_fd, front_fd, end_fd;
	char *buf = ctx->buf;
	int events = ctx->events;
	struct epoll_event evt;
	struct sockaddr_in addr_in;
	int ret;
	int cpu_id = ctx->cpu_id;

	ep_fd = ctx->ep_fd;
	front_fd = ctx->fd;

	//FIXME: What else should I do.
	if (events & (EPOLLHUP | EPOLLERR)) {
		printf("process_read_frontend() with events HUP or ERR\n");
		goto free_back;
	}

	print_d("Process read event[%02x] on front-end socket %d\n", events, front_fd);

	ret = read(front_fd, buf, MAX_BUFSIZE);
	if (ret < 0)
	{
		wdata[cpu_id].read_cnt++;
		perror("process_read_frontend() can't read client socket");
		goto free_back;
	}

	ctx->data_len = ret;

	print_d("Read %d from front-end socket %d\n", ret, front_fd);

	//Remove interested read event for front-end socket
	evt.events = EPOLLHUP | EPOLLERR;
	evt.data.ptr = ctx;

	ret = epoll_ctl(ep_fd, EPOLL_CTL_MOD, front_fd, &evt);
	if (ret < 0) {
		perror("Unable to add client socket read event to epoll");
		goto free_back;
	}

	int flags;

	ret = socket(AF_INET, SOCK_STREAM, 0);
	if (ret < 0) {
		perror("Unable to create new socket for backend");
		goto free_back;
	}

	end_fd = ret;
	ctx->end_fd = end_fd;

	print_d("Create socket %d\n", ret);

	flags = fcntl(ret, F_GETFL, 0);
	flags |= O_NONBLOCK;
	fcntl(ret, F_SETFL, flags);

	struct linger ling = {1, 0};

	ret = setsockopt(end_fd, SOL_SOCKET, SO_LINGER, (void *)&ling, sizeof(ling));
	if (ret < 0) {
		perror("Unable to set socket linger option");
		goto free_back;
	}

	select_backend(&addr_in);

	ret = connect(end_fd, (struct sockaddr *)&addr_in, sizeof(struct sockaddr));
	if (ret < 0) {
		if (errno != EINPROGRESS) {
			perror("Unable to connect to back end server");
			goto free_back;
		}
	}

	ctx->handler = process_write_backend;
	ctx->flags |= PROXY_BACKEND_EVENT;

	evt.events = EPOLLOUT | EPOLLHUP | EPOLLERR;
	evt.data.ptr = ctx;

	ret = epoll_ctl(ep_fd, EPOLL_CTL_ADD, end_fd, &evt);
	if (ret < 0) {
		perror("Unable to add client socket read event to epoll");
		goto free_back;
	}

	ctx->end_fd_added = 1;

	print_d("Add back-end socket %d to epoll\n", end_fd);

	goto back;

free_back:

	print_d("cpu[%d] close socket %d\n", cpu_id, ctx->fd);

	process_close(ctx);
	free_context(ctx);

back:
	return;
}
Beispiel #27
0
static int
relay_back_cf( ConfigArgs *c )
{
	relay_back_info	*ri = ( relay_back_info * )c->be->be_private;
	int		rc = 0;

	if ( c->op == SLAP_CONFIG_EMIT ) {
		if ( ri != NULL && !BER_BVISNULL( &ri->ri_realsuffix ) ) {
			value_add_one( &c->rvalue_vals, &ri->ri_realsuffix );
			return 0;
		}
		return 1;

	} else if ( c->op == LDAP_MOD_DELETE ) {
		if ( !BER_BVISNULL( &ri->ri_realsuffix ) ) {
			ch_free( ri->ri_realsuffix.bv_val );
			BER_BVZERO( &ri->ri_realsuffix );
			ri->ri_bd = NULL;
			return 0;
		}
		return 1;

	} else {
		BackendDB *bd;

		assert( ri != NULL );
		assert( BER_BVISNULL( &ri->ri_realsuffix ) );

		if ( c->be->be_nsuffix == NULL ) {
			snprintf( c->cr_msg, sizeof( c->cr_msg),
				"\"relay\" directive "
				"must appear after \"suffix\"" );
			Log2( LDAP_DEBUG_ANY, LDAP_LEVEL_ERR,
				"%s: %s.\n", c->log, c->cr_msg );
			rc = 1;
			goto relay_done;
		}

		if ( !BER_BVISNULL( &c->be->be_nsuffix[ 1 ] ) ) {
			snprintf( c->cr_msg, sizeof( c->cr_msg),
				"relaying of multiple suffix "
				"database not supported" );
			Log2( LDAP_DEBUG_ANY, LDAP_LEVEL_ERR,
				"%s: %s.\n", c->log, c->cr_msg );
			rc = 1;
			goto relay_done;
		}

		bd = select_backend( &c->value_ndn, 1 );
		if ( bd == NULL ) {
			snprintf( c->cr_msg, sizeof( c->cr_msg),
				"cannot find database "
				"of relay dn \"%s\" "
				"in \"olcRelay <dn>\"\n",
				c->value_dn.bv_val );
			Log2( LDAP_DEBUG_CONFIG, LDAP_LEVEL_ERR,
				"%s: %s.\n", c->log, c->cr_msg );

		} else if ( bd->be_private == c->be->be_private ) {
			snprintf( c->cr_msg, sizeof( c->cr_msg),
				"relay dn \"%s\" would call self "
				"in \"relay <dn>\" line\n",
				c->value_dn.bv_val );
			Log2( LDAP_DEBUG_ANY, LDAP_LEVEL_ERR,
				"%s: %s.\n", c->log, c->cr_msg );
			rc = 1;
			goto relay_done;
		}

		ri->ri_realsuffix = c->value_ndn;
		BER_BVZERO( &c->value_ndn );

relay_done:;
		ch_free( c->value_dn.bv_val );
		ch_free( c->value_ndn.bv_val );
	}

	return rc;
}
Beispiel #28
0
static int
dynlist_compare( Operation *op, SlapReply *rs )
{
	slap_overinst	*on = (slap_overinst *)op->o_bd->bd_info;
	dynlist_info_t	*dli = (dynlist_info_t *)on->on_bi.bi_private;
	Operation o = *op;
	Entry *e = NULL;
	dynlist_map_t *dlm;
	BackendDB *be;

	for ( ; dli != NULL; dli = dli->dli_next ) {
		for ( dlm = dli->dli_dlm; dlm; dlm = dlm->dlm_next )
			if ( op->oq_compare.rs_ava->aa_desc == dlm->dlm_member_ad )
				break;

		if ( dlm ) {
			/* This compare is for one of the attributes we're
			 * interested in. We'll use slapd's existing dyngroup
			 * evaluator to get the answer we want.
			 */
			BerVarray id = NULL, authz = NULL;

			o.o_do_not_cache = 1;

			if ( ad_dgIdentity && backend_attribute( &o, NULL, &o.o_req_ndn,
				ad_dgIdentity, &id, ACL_READ ) == LDAP_SUCCESS )
			{
				/* if not rootdn and dgAuthz is present,
				 * check if user can be authorized as dgIdentity */
				if ( ad_dgAuthz && !BER_BVISEMPTY( id ) && !be_isroot( op )
					&& backend_attribute( &o, NULL, &o.o_req_ndn,
						ad_dgAuthz, &authz, ACL_READ ) == LDAP_SUCCESS )
				{
					
					rs->sr_err = slap_sasl_matches( op, authz,
						&o.o_ndn, &o.o_ndn );
					ber_bvarray_free_x( authz, op->o_tmpmemctx );
					if ( rs->sr_err != LDAP_SUCCESS ) {
						goto done;
					}
				}

				o.o_dn = *id;
				o.o_ndn = *id;
				o.o_groups = NULL; /* authz changed, invalidate cached groups */
			}

			rs->sr_err = backend_group( &o, NULL, &o.o_req_ndn,
				&o.oq_compare.rs_ava->aa_value, dli->dli_oc, dli->dli_ad );
			switch ( rs->sr_err ) {
			case LDAP_SUCCESS:
				rs->sr_err = LDAP_COMPARE_TRUE;
				break;

			case LDAP_NO_SUCH_OBJECT:
				/* NOTE: backend_group() returns noSuchObject
				 * if op_ndn does not exist; however, since
				 * dynamic list expansion means that the
				 * member attribute is virtually present, the
				 * non-existence of the asserted value implies
				 * the assertion is FALSE rather than
				 * UNDEFINED */
				rs->sr_err = LDAP_COMPARE_FALSE;
				break;
			}

done:;
			if ( id ) ber_bvarray_free_x( id, o.o_tmpmemctx );

			return SLAP_CB_CONTINUE;
		}
	}

	be = select_backend( &o.o_req_ndn, 1 );
	if ( !be || !be->be_search ) {
		return SLAP_CB_CONTINUE;
	}

	if ( overlay_entry_get_ov( &o, &o.o_req_ndn, NULL, NULL, 0, &e, on ) !=
		LDAP_SUCCESS || e == NULL )
	{
		return SLAP_CB_CONTINUE;
	}

	/* check for dynlist objectClass; done if not found */
	dli = (dynlist_info_t *)on->on_bi.bi_private;
	while ( dli != NULL && !is_entry_objectclass_or_sub( e, dli->dli_oc ) ) {
		dli = dli->dli_next;
	}
	if ( dli == NULL ) {
		goto release;
	}

	if ( ad_dgIdentity ) {
		Attribute *id = attrs_find( e->e_attrs, ad_dgIdentity );
		if ( id ) {
			Attribute *authz;

			/* if not rootdn and dgAuthz is present,
			 * check if user can be authorized as dgIdentity */
			if ( ad_dgAuthz && !BER_BVISEMPTY( &id->a_nvals[0] ) && !be_isroot( op )
				&& ( authz = attrs_find( e->e_attrs, ad_dgAuthz ) ) )
			{
				if ( slap_sasl_matches( op, authz->a_nvals,
					&o.o_ndn, &o.o_ndn ) != LDAP_SUCCESS )
				{
					goto release;
				}
			}

			o.o_dn = id->a_vals[0];
			o.o_ndn = id->a_nvals[0];
			o.o_groups = NULL;
		}
	}

	/* generate dynamic list with dynlist_response() and compare */
	{
		SlapReply	r = { REP_SEARCH };
		dynlist_cc_t	dc = { { 0, dynlist_sc_compare_entry, 0, 0 }, 0 };
		AttributeName	an[2];

		dc.dc_ava = op->orc_ava;
		dc.dc_res = &rs->sr_err;
		o.o_callback = (slap_callback *) &dc;

		o.o_tag = LDAP_REQ_SEARCH;
		o.ors_limit = NULL;
		o.ors_tlimit = SLAP_NO_LIMIT;
		o.ors_slimit = SLAP_NO_LIMIT;

		o.ors_filterstr = *slap_filterstr_objectClass_pres;
		o.ors_filter = (Filter *) slap_filter_objectClass_pres;

		o.ors_scope = LDAP_SCOPE_BASE;
		o.ors_deref = LDAP_DEREF_NEVER;
		an[0].an_name = op->orc_ava->aa_desc->ad_cname;
		an[0].an_desc = op->orc_ava->aa_desc;
		BER_BVZERO( &an[1].an_name );
		o.ors_attrs = an;
		o.ors_attrsonly = 0;

		o.o_acl_priv = ACL_COMPARE;

		o.o_bd = be;
		(void)be->be_search( &o, &r );

		if ( o.o_dn.bv_val != op->o_dn.bv_val ) {
			slap_op_groups_free( &o );
		}
	}

release:;
	if ( e != NULL ) {
		overlay_entry_release_ov( &o, e, 0, on );
	}

	return SLAP_CB_CONTINUE;
}
Beispiel #29
0
int
fe_op_search( Operation *op, SlapReply *rs )
{
	BackendDB		*bd = op->o_bd;

	if ( op->ors_scope == LDAP_SCOPE_BASE ) {
		Entry *entry = NULL;

		if ( BER_BVISEMPTY( &op->o_req_ndn ) ) {
#ifdef LDAP_CONNECTIONLESS
			/* Ignore LDAPv2 CLDAP Root DSE queries */
			if (op->o_protocol == LDAP_VERSION2 && op->o_conn->c_is_udp) {
				goto return_results;
			}
#endif
			/* check restrictions */
			if( backend_check_restrictions( op, rs, NULL ) != LDAP_SUCCESS ) {
				send_ldap_result( op, rs );
				goto return_results;
			}

			rs->sr_err = root_dse_info( op->o_conn, &entry, &rs->sr_text );

		} else if ( bvmatch( &op->o_req_ndn, &frontendDB->be_schemandn ) ) {
			/* check restrictions */
			if( backend_check_restrictions( op, rs, NULL ) != LDAP_SUCCESS ) {
				send_ldap_result( op, rs );
				goto return_results;
			}

			rs->sr_err = schema_info( &entry, &rs->sr_text );
		}

		if( rs->sr_err != LDAP_SUCCESS ) {
			send_ldap_result( op, rs );
			goto return_results;

		} else if ( entry != NULL ) {
			if ( get_assert( op ) &&
				( test_filter( op, entry, get_assertion( op )) != LDAP_COMPARE_TRUE )) {
				rs->sr_err = LDAP_ASSERTION_FAILED;
				goto fail1;
			}

			rs->sr_err = test_filter( op, entry, op->ors_filter );

			if( rs->sr_err == LDAP_COMPARE_TRUE ) {
				/* note: we set no limits because either
				 * no limit is specified, or at least 1
				 * is specified, and we're going to return
				 * at most one entry */			
				op->ors_slimit = SLAP_NO_LIMIT;
				op->ors_tlimit = SLAP_NO_LIMIT;

				rs->sr_entry = entry;
				rs->sr_attrs = op->ors_attrs;
				rs->sr_operational_attrs = NULL;
				rs->sr_flags = 0;
				send_search_entry( op, rs );
				rs->sr_entry = NULL;
				rs->sr_operational_attrs = NULL;
			}
			rs->sr_err = LDAP_SUCCESS;
fail1:
			entry_free( entry );
			send_ldap_result( op, rs );
			goto return_results;
		}
	}

	if( BER_BVISEMPTY( &op->o_req_ndn ) && !BER_BVISEMPTY( &default_search_nbase ) ) {
		slap_sl_free( op->o_req_dn.bv_val, op->o_tmpmemctx );
		slap_sl_free( op->o_req_ndn.bv_val, op->o_tmpmemctx );

		ber_dupbv_x( &op->o_req_dn, &default_search_base, op->o_tmpmemctx );
		ber_dupbv_x( &op->o_req_ndn, &default_search_nbase, op->o_tmpmemctx );
	}

	/*
	 * We could be serving multiple database backends.  Select the
	 * appropriate one, or send a referral to our "referral server"
	 * if we don't hold it.
	 */

	op->o_bd = select_backend( &op->o_req_ndn, 1 );
	if ( op->o_bd == NULL ) {
		rs->sr_ref = referral_rewrite( default_referral,
			NULL, &op->o_req_dn, op->ors_scope );

		if (!rs->sr_ref) rs->sr_ref = default_referral;
		rs->sr_err = LDAP_REFERRAL;
		op->o_bd = bd;
		send_ldap_result( op, rs );

		if (rs->sr_ref != default_referral)
		ber_bvarray_free( rs->sr_ref );
		rs->sr_ref = NULL;
		goto return_results;
	}

	/* check restrictions */
	if( backend_check_restrictions( op, rs, NULL ) != LDAP_SUCCESS ) {
		send_ldap_result( op, rs );
		goto return_results;
	}

	/* check for referrals */
	if( backend_check_referrals( op, rs ) != LDAP_SUCCESS ) {
		goto return_results;
	}

	if ( SLAP_SHADOW(op->o_bd) && get_dontUseCopy(op) ) {
		/* don't use shadow copy */
		BerVarray defref = op->o_bd->be_update_refs
			? op->o_bd->be_update_refs : default_referral;

		if( defref != NULL ) {
			rs->sr_ref = referral_rewrite( defref,
				NULL, &op->o_req_dn, op->ors_scope );
			if( !rs->sr_ref) rs->sr_ref = defref;
			rs->sr_err = LDAP_REFERRAL;
			send_ldap_result( op, rs );

			if (rs->sr_ref != defref) ber_bvarray_free( rs->sr_ref );

		} else {
			send_ldap_error( op, rs, LDAP_UNWILLING_TO_PERFORM,
				"copy not used; no referral information available" );
		}

	} else if ( op->o_bd->be_search ) {
		if ( limits_check( op, rs ) == 0 ) {
			/* actually do the search and send the result(s) */
			(op->o_bd->be_search)( op, rs );
		}
		/* else limits_check() sends error */

	} else {
		send_ldap_error( op, rs, LDAP_UNWILLING_TO_PERFORM,
			"operation not supported within namingContext" );
	}

return_results:;
	op->o_bd = bd;
	return rs->sr_err;
}
Beispiel #30
0
static int
idattr_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 )
{
    idattr_t		*id = (idattr_t *)priv;
    Entry   *user = NULL;
    int		rc = LDAP_INSUFFICIENT_ACCESS;
    int		user_rc = LDAP_INSUFFICIENT_ACCESS;
    int		target_rc = LDAP_INSUFFICIENT_ACCESS;
    Backend		*be = op->o_bd,
                 *group_be = NULL,
                  *user_be = NULL;
    AttributeDescription *searchAttr = NULL;
    ObjectClass *searchObject = NULL;
    struct berval *searchTarget = NULL;
    Entry *searchEntry = NULL;

    ACL_INVALIDATE( *deny );

    Debug( LDAP_DEBUG_ACL, "idattr_dynacl_mask: pat(%s) type(%d) op(%d)\n", id->idattr_pat.bv_val, id->idattr_type, id->idattr_ops );

    Debug( LDAP_DEBUG_ACL, "idattr_dynacl_mask: target(%s) op->o_ndn(%s)\n", target->e_nname.bv_val, op->o_ndn.bv_val, 0 );

    if (id->idattr_ops && (id->idattr_ops != op->o_tag)) {
        Debug( LDAP_DEBUG_ACL, "idattr_dynacl_mask:  Operation Not Allowed - Ops allowed (%d), Requested Op (%d)\n", id->idattr_ops, op->o_tag, 0 );
        // LDAP_INSUFFICIENT_ACCESS
        return 0;
    }

    if (!op->o_conn->c_authz.c_sai_krb5_auth_data_provisioned) {
        user_be = op->o_bd = select_backend( &op->o_ndn, 0);
        if ( op->o_bd == NULL ) {
            Debug( LDAP_DEBUG_ACL, "idattr_dynacl_mask: op->o_bd == NULL \n", 0, 0, 0 );
            op->o_bd = be;
            return 0;
        }
    }
    // check ACL TYPE
    Debug( LDAP_DEBUG_ACL, "idattr_dynacl_mask: idattr_type(%d)\n", id->idattr_type, 0, 0 );
    if (id->idattr_type == UUID_TYPE || id->idattr_type == OWNER_TYPE) {
        searchAttr = idattr_uuid;
        searchObject = idattr_extensible_object;
        searchTarget = &op->o_ndn;
    } else if (id->idattr_type == SID_TYPE) {
        searchAttr = idattr_sid;
        searchObject = idattr_extensible_object;
        searchTarget = &op->o_conn->c_authz.sai_ndn;
    } else if (id->idattr_type == SELFWRITE_TYPE) {
        searchAttr = id->idattr_selfattrDesc;
        searchObject = idattr_extensible_object;
        searchTarget = &op->o_ndn;
    } else if (id->idattr_type == USERS_TYPE) {
        if (BER_BVISEMPTY( &op->o_ndn )) {
            // LDAP_INSUFFICIENT_ACCESS
            op->o_bd = be;
            return 0;
        } else {
            // check for APPLYTO clause
            if (id->idattr_applyto) {
                rc = idattr_check_applyto(op, target, searchAttr, id);
            } else {
                rc =  LDAP_SUCCESS;
            }
            goto assignaccess;
        }
    } else {
        Debug( LDAP_DEBUG_ACL, "idattr_dynacl_mask: unknown idattr_type(%s)\n", id->idattr_type, 0, 0 );
        // LDAP_INSUFFICIENT_ACCESS
        return 0;
    }
    if (op->o_conn->c_authz.c_sai_krb5_auth_data_provisioned) {
        user_rc = LDAP_SUCCESS;
    } else if (searchAttr) {
        // lookup user record
        user_rc = be_entry_get_rw( op, searchTarget, NULL, searchAttr, 0, &user );

        Debug( LDAP_DEBUG_ACL, "idattr_dynacl_mask: be_entry_get_rw user_rc(%d) user(%x) \n", user_rc, user, 0 );

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

    if ( user_rc == LDAP_SUCCESS || user != NULL ) {
        user_rc = idattr_check_isuser(op, user, searchAttr, id);

        if (user_rc == LDAP_SUCCESS) {
            switch ( id->idattr_type ) {
            case SELFWRITE_TYPE:
                user_rc = idattr_check_selfwrite(op, target, user, val, id);
                break;
            case OWNER_TYPE:
                user_rc = idattr_check_isowner(op, user, target, searchAttr, id);
                break;
            case UUID_TYPE:
            case SID_TYPE:
                user_rc = LDAP_SUCCESS;
                break;
            default:
                break;
            }

            if (user_rc == LDAP_SUCCESS) {
                if (id->idattr_applyto) {
                    rc = idattr_check_applyto(op, target, searchAttr, id);
                } else {
                    rc = LDAP_SUCCESS;
                }
            }
        }
    } else {
        rc = LDAP_NO_SUCH_OBJECT;
    }

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

cleanup:

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

    return 0;
}