Exemple #1
0
/*
 * controlType = LDAP_CONTROL_GET_EFFECTIVE_RIGHTS;
 * criticality = n/a;
 * controlValue = OCTET STRING of BER encoding of the SEQUENCE of
 *				  ENUMERATED LDAP code
 */
void
_ger_set_response_control (
	Slapi_PBlock	*pb,
	int				iscritical,
	int				rc
	)
{
	LDAPControl **resultctrls = NULL;
	LDAPControl gerrespctrl;
	BerElement *ber = NULL;
	struct berval *berval = NULL;
	int found = 0;
	int i;

	if ( (ber = der_alloc ()) == NULL )
	{
		goto bailout;
	}

	/* begin sequence, enumeration, end sequence */
	ber_printf ( ber, "{e}", rc );
	if ( ber_flatten ( ber, &berval ) != LDAP_SUCCESS )
	{
		goto bailout;
	}
	gerrespctrl.ldctl_oid = LDAP_CONTROL_GET_EFFECTIVE_RIGHTS;
	gerrespctrl.ldctl_iscritical = iscritical;
	gerrespctrl.ldctl_value.bv_val = berval->bv_val;
	gerrespctrl.ldctl_value.bv_len = berval->bv_len;

	slapi_pblock_get ( pb, SLAPI_RESCONTROLS, &resultctrls );
	for (i = 0; resultctrls && resultctrls[i]; i++)
	{
		if (strcmp(resultctrls[i]->ldctl_oid, LDAP_CONTROL_GET_EFFECTIVE_RIGHTS) == 0)
		{
			/*
			 * We get here if search returns more than one entry
			 * and this is not the first entry.
			 */
			ldap_control_free ( resultctrls[i] );
			resultctrls[i] = slapi_dup_control (&gerrespctrl);
			found = 1;
			break;
		}
	}

	if ( !found )
	{
		/* slapi_pblock_set() will dup the control */
		slapi_pblock_set ( pb, SLAPI_ADD_RESCONTROL, &gerrespctrl );
	}

bailout:
	ber_free ( ber, 1 );	/* ber_free() checks for NULL param */
	ber_bvfree ( berval );	/* ber_bvfree() checks for NULL param */
}
Exemple #2
0
static int
pblock_add_control( Slapi_PBlock *pb, LDAPControl *control )
{
	LDAPControl **controls = NULL;
	size_t i;

	pblock_get_default( pb, SLAPI_RESCONTROLS, (void **)&controls );

	if ( controls != NULL ) {
		for ( i = 0; controls[i] != NULL; i++ )
			;
	} else {
		i = 0;
	}

	controls = (LDAPControl **)slapi_ch_realloc( (char *)controls,
		( i + 2 ) * sizeof(LDAPControl *));
	controls[i++] = slapi_dup_control( control );
	controls[i] = NULL;

	return pblock_set_default( pb, SLAPI_RESCONTROLS, (void *)controls );
}
Exemple #3
0
/*
 * controlType = LDAP_CONTROL_PAGEDRESULTS;
 * criticality = n/a;
 * controlValue:
 *   realSearchControlValue ::= SEQUENCE {
 *   size INTEGER (0..maxInt),
 *   -- requested page size from client
 *   -- result set size estimate from server
 *   cookie OCTET STRING
 *   }
 */
void
pagedresults_set_response_control( Slapi_PBlock *pb, int iscritical,
                                   ber_int_t estimate, int current_search_count,
                                   int index )
{
    LDAPControl **resultctrls = NULL;
    LDAPControl pr_respctrl;
    BerElement *ber = NULL;
    struct berval *berval = NULL;
    char *cookie_str = NULL;
    int found = 0;
    int i;

    LDAPDebug1Arg(LDAP_DEBUG_TRACE,
                  "--> pagedresults_set_response_control: idx=%d\n", index);

    if ( (ber = der_alloc()) == NULL )
    {
        goto bailout;
    }

    /* begin sequence, payload, end sequence */
    if (current_search_count < 0) {
        cookie_str = slapi_ch_strdup("");
    } else {
        cookie_str = slapi_ch_smprintf("%d", index);
    }
    ber_printf ( ber, "{io}", estimate, cookie_str, strlen(cookie_str) );
    if ( ber_flatten ( ber, &berval ) != LDAP_SUCCESS )
    {
        goto bailout;
    }
    pr_respctrl.ldctl_oid = LDAP_CONTROL_PAGEDRESULTS;
    pr_respctrl.ldctl_iscritical = iscritical;
    pr_respctrl.ldctl_value.bv_val = berval->bv_val;
    pr_respctrl.ldctl_value.bv_len = berval->bv_len;

    slapi_pblock_get ( pb, SLAPI_RESCONTROLS, &resultctrls );
    for (i = 0; resultctrls && resultctrls[i]; i++)
    {
        if (strcmp(resultctrls[i]->ldctl_oid, LDAP_CONTROL_PAGEDRESULTS) == 0)
        {
            /*
             * We get here if search returns more than one entry
             * and this is not the first entry.
             */
            ldap_control_free ( resultctrls[i] );
            resultctrls[i] = slapi_dup_control (&pr_respctrl);
            found = 1;
            break;
        }
    }

    if ( !found )
    {
        /* slapi_pblock_set() will dup the control */
        slapi_pblock_set ( pb, SLAPI_ADD_RESCONTROL, &pr_respctrl );
    }

bailout:
    slapi_ch_free_string(&cookie_str);
    ber_free ( ber, 1 );      /* ber_free() checks for NULL param */
    ber_bvfree ( berval );    /* ber_bvfree() checks for NULL param */

    LDAPDebug1Arg(LDAP_DEBUG_TRACE,
                  "<-- pagedresults_set_response_control: idx=%d\n", index);
}
Exemple #4
0
/*
 * Check if there are any persistent searches.  If so,
 * the check to see if the chgtype is one of those the
 * client is interested in.  If so, then check to see if
 * the entry matches any of the filters the searches.
 * If so, then enqueue the entry on that persistent search's
 * ps_entryqueue and signal it to wake up and send the entry.
 *
 * Note that if eprev is NULL we assume that the entry's DN
 * was not changed by the op. that called this function.  If
 * chgnum is 0 it is unknown so we won't ever send it to a
 * client in the EntryChangeNotification control.
 */
void
ps_service_persistent_searches( Slapi_Entry *e, Slapi_Entry *eprev, ber_int_t chgtype,
	ber_int_t chgnum )
{
	LDAPControl *ctrl = NULL;
	PSearch	*ps = NULL;
	PSEQNode *pe = NULL;
	int  matched = 0;
	const char *edn;

	if ( !PS_IS_INITIALIZED()) {
		return;
	}

	if ( NULL == e ) {
		/* For now, some backends such as the chaining backend do not provide a post-op entry */
		return;
	}

	PSL_LOCK_READ();
	edn = slapi_entry_get_dn_const(e);

	for ( ps = psearch_list ? psearch_list->pl_head : NULL; NULL != ps; ps = ps->ps_next ) {
		char *origbase = NULL;
		Slapi_DN *base = NULL;
		Slapi_Filter	*f;
		int		scope;

		/* Skip the node that doesn't meet the changetype,
		 * or is unable to use the change in ps_send_results()
		 */
		if (( ps->ps_changetypes & chgtype ) == 0 ||
				ps->ps_pblock->pb_op == NULL ||
				slapi_op_abandoned( ps->ps_pblock ) ) {
			continue;
		}

		slapi_log_error(SLAPI_LOG_CONNS, "Persistent Search",
						"conn=%" NSPRIu64 " op=%d entry %s with chgtype %d "
						"matches the ps changetype %d\n",
						ps->ps_pblock->pb_conn->c_connid,
						ps->ps_pblock->pb_op->o_opid,
						edn, chgtype, ps->ps_changetypes);

		slapi_pblock_get( ps->ps_pblock, SLAPI_SEARCH_FILTER, &f );
		slapi_pblock_get( ps->ps_pblock, SLAPI_ORIGINAL_TARGET_DN, &origbase );
		slapi_pblock_get( ps->ps_pblock, SLAPI_SEARCH_TARGET_SDN, &base );
		slapi_pblock_get( ps->ps_pblock, SLAPI_SEARCH_SCOPE, &scope );
		if (NULL == base) {
			base = slapi_sdn_new_dn_byref(origbase);
			slapi_pblock_set(ps->ps_pblock, SLAPI_SEARCH_TARGET_SDN, base);
		}

		/*
		 * See if the entry meets the scope and filter criteria.
		 * We cannot do the acl check here as this thread
		 * would then potentially clash with the ps_send_results()
		 * thread on the aclpb in ps->ps_pblock.
		 * By avoiding the acl check in this thread, and leaving all the acl
		 * checking to the ps_send_results() thread we avoid
		 * the ps_pblock contention problem.
		 * The lesson here is "Do not give multiple threads arbitary access
		 * to the same pblock" this kind of muti-threaded access
		 * to the same pblock must be done carefully--there is currently no
		 * generic satisfactory way to do this.
		*/
		if ( slapi_sdn_scope_test( slapi_entry_get_sdn_const(e), base, scope ) &&
			 slapi_vattr_filter_test( ps->ps_pblock, e, f, 0 /* verify_access */ ) == 0 ) {
			PSEQNode *pOldtail;

			/* The scope and the filter match - enqueue it */

			matched++;
			pe = (PSEQNode *)slapi_ch_calloc( 1, sizeof( PSEQNode ));
			pe->pe_entry = slapi_entry_dup( e );
			if ( ps->ps_send_entchg_controls ) {
				/* create_entrychange_control() is more
				 * expensive than slapi_dup_control()
				 */
				if ( ctrl == NULL ) {
					int rc;
					rc = create_entrychange_control( chgtype, chgnum,
							eprev ? slapi_entry_get_dn_const(eprev) : NULL,
							&ctrl );
					if ( rc != LDAP_SUCCESS ) {
		   				LDAPDebug( LDAP_DEBUG_ANY, "ps_service_persistent_searches:"
						" unable to create EntryChangeNotification control for"
						" entry \"%s\" -- control won't be sent.\n",
						slapi_entry_get_dn_const(e), 0, 0 );
					}
				}
				if ( ctrl ) {
					pe->pe_ctrls[0] = slapi_dup_control( ctrl );
				}
			}

			/* Put it on the end of the list for this pers search */
			PR_Lock( ps->ps_lock );
			pOldtail = ps->ps_eq_tail;
			ps->ps_eq_tail = pe;
			if ( NULL == ps->ps_eq_head ) {
				ps->ps_eq_head = ps->ps_eq_tail;
			}
			else {
				pOldtail->pe_next = ps->ps_eq_tail;
			}
			PR_Unlock( ps->ps_lock );
		}
	}

   	PSL_UNLOCK_READ();

	/* Were there any matches? */
	if ( matched ) {
		ldap_control_free( ctrl );
		/* Turn 'em loose */
		ps_wakeup_all();
		LDAPDebug( LDAP_DEBUG_TRACE, "ps_service_persistent_searches: enqueued entry "
			"\"%s\" on %d persistent search lists\n", slapi_entry_get_dn_const(e), matched, 0 );
	} else {
		LDAPDebug( LDAP_DEBUG_TRACE, "ps_service_persistent_searches: entry "
			"\"%s\" not enqueued on any persistent search lists\n", slapi_entry_get_dn_const(e), 0, 0 );
	}

}
Exemple #5
0
/* 
	This function scans the array of controls and updates the Repl_Agmt's 
	Dirsync_Private if the dirsync control is found. 

*/
void windows_private_update_dirsync_control(const Repl_Agmt *ra,LDAPControl **controls )
{

	Dirsync_Private *dp;
    int foundDirsyncControl;
	int i;
	LDAPControl *dirsync = NULL;
	BerElement *ber = NULL;
	ber_int_t hasMoreData;
	ber_int_t maxAttributeCount;
	BerValue  *serverCookie = NULL;
#ifdef FOR_DEBUGGING
	int return_value = LDAP_SUCCESS;
#endif

	LDAPDebug0Args( LDAP_DEBUG_TRACE, "=> windows_private_update_dirsync_control\n" );

    PR_ASSERT(ra);

	dp = (Dirsync_Private *) agmt_get_priv(ra);
	PR_ASSERT (dp);
	
	if (NULL != controls )
	{
		foundDirsyncControl = 0;
		for ( i = 0; (( controls[i] != NULL ) && ( !foundDirsyncControl )); i++ ) {
			foundDirsyncControl = !strcmp( controls[i]->ldctl_oid, REPL_DIRSYNC_CONTROL_OID );
		}

		if ( !foundDirsyncControl )
		{
#ifdef FOR_DEBUGGING
			return_value = LDAP_CONTROL_NOT_FOUND;
#endif
			goto choke;
		}
		else if (!controls[i-1]->ldctl_value.bv_val) {
#ifdef FOR_DEBUGGING
			return_value = LDAP_CONTROL_NOT_FOUND;
#endif
			goto choke;
		}
		else
		{
			dirsync = slapi_dup_control( controls[i-1]);
		}

		ber = ber_init( &dirsync->ldctl_value ) ;

		if (ber_scanf( ber, "{iiO}", &hasMoreData, &maxAttributeCount, &serverCookie) == LBER_ERROR)
		{
#ifdef FOR_DEBUGGING
			return_value =  LDAP_CONTROL_NOT_FOUND;
#endif
			goto choke;
		}

		slapi_ch_free_string(&dp->dirsync_cookie);
		dp->dirsync_cookie = ( char* ) slapi_ch_malloc(serverCookie->bv_len + 1);

		memcpy(dp->dirsync_cookie, serverCookie->bv_val, serverCookie->bv_len);
		dp->dirsync_cookie_len = (int) serverCookie->bv_len; /* XXX shouldn't cast? */

		/* dp->dirsync_maxattributecount = maxAttributeCount; We don't need to keep this */
		dp->dirsync_cookie_has_more = hasMoreData;

choke:
		ber_bvfree(serverCookie);
		ber_free(ber,1);
		ldap_control_free(dirsync);
	}
	else
	{
#ifdef FOR_DEBUGGING
		return_value = LDAP_CONTROL_NOT_FOUND;
#endif
	}

#ifdef FOR_DEBUGGING
	LDAPDebug1Arg( LDAP_DEBUG_TRACE, "<= windows_private_update_dirsync_control: rc=%d\n", return_value);
#else
	LDAPDebug0Args( LDAP_DEBUG_TRACE, "<= windows_private_update_dirsync_control\n" );
#endif
}