Esempio n. 1
0
struct berval * slap_passwd_return(
    struct berval		*cred )
{
    int rc;
    struct berval *bv = NULL;
    char berbuf[LBER_ELEMENT_SIZEOF];
    /* opaque structure, size unknown but smaller than berbuf */
    BerElement *ber = (BerElement *)berbuf;

    assert( cred != NULL );

#ifdef NEW_LOGGING
    LDAP_LOG( OPERATION, ENTRY,
              "slap_passwd_return: %ld\n",(long)cred->bv_len, 0, 0 );
#else
    Debug( LDAP_DEBUG_TRACE, "slap_passwd_return: %ld\n",
           (long) cred->bv_len, 0, 0 );
#endif

    ber_init_w_nullc( ber, LBER_USE_DER );

    rc = ber_printf( ber, "{tON}",
                     LDAP_TAG_EXOP_MODIFY_PASSWD_GEN, cred );

    if( rc >= 0 ) {
        (void) ber_flatten( ber, &bv );
    }

    ber_free_buf( ber );

    return bv;
}
Esempio n. 2
0
Filter *
str2filter_x( Operation *op, const char *str )
{
	int rc;
	Filter	*f = NULL;
	BerElementBuffer berbuf;
	BerElement *ber = (BerElement *)&berbuf;
	const char *text = NULL;

	Debug( LDAP_DEBUG_FILTER, "str2filter \"%s\"\n", str, 0, 0 );

	if ( str == NULL || *str == '\0' ) {
		return NULL;
	}

	ber_init2( ber, NULL, LBER_USE_DER );
	if ( op->o_tmpmemctx ) {
		ber_set_option( ber, LBER_OPT_BER_MEMCTX, &op->o_tmpmemctx );
	}

	rc = ldap_pvt_put_filter( ber, str );
	if( rc < 0 ) {
		goto done;
	}

	ber_reset( ber, 1 );

	rc = get_filter( op, ber, &f, &text );

done:
	ber_free_buf( ber );

	return f;
}
Esempio n. 3
0
struct berval * slap_passwd_return(
	struct berval		*cred )
{
	int rc;
	struct berval *bv = NULL;
	BerElementBuffer berbuf;
	/* opaque structure, size unknown but smaller than berbuf */
	BerElement *ber = (BerElement *)&berbuf;

	assert( cred != NULL );

	Debug( LDAP_DEBUG_TRACE, "slap_passwd_return: %ld\n",
		(long) cred->bv_len, 0, 0 );
	
	ber_init_w_nullc( ber, LBER_USE_DER );

	rc = ber_printf( ber, "{tON}",
		LDAP_TAG_EXOP_MODIFY_PASSWD_GEN, cred );

	if( rc >= 0 ) {
		(void) ber_flatten( ber, &bv );
	}

	ber_free_buf( ber );

	return bv;
}
Esempio n. 4
0
static int
dupent_response_done( Operation *op, SlapReply *rs )
{
	BerElementBuffer	berbuf;
	BerElement			*ber = (BerElement *) &berbuf;
	struct berval		ctrlval;
	LDAPControl			*ctrl, *ctrlsp[2];

	ber_init2( ber, NULL, LBER_USE_DER );

	/*

      DuplicateEntryResponseDone ::= SEQUENCE { 
         resultCode,     -- From [RFC2251] 
         errorMessage    [0] LDAPString OPTIONAL, 
         attribute       [1] AttributeDescription OPTIONAL } 

	 */

	ber_printf( ber, "{i}", rs->sr_err );
	if ( ber_flatten2( ber, &ctrlval, 0 ) == -1 ) {
		ber_free_buf( ber );
		if ( op->o_dupent == SLAP_CONTROL_CRITICAL ) {
			return LDAP_CONSTRAINT_VIOLATION;
		}
		return SLAP_CB_CONTINUE;
	}

	ctrl = op->o_tmpcalloc( 1,
		sizeof( LDAPControl ) + ctrlval.bv_len + 1,
		op->o_tmpmemctx );
	ctrl->ldctl_value.bv_val = (char *)&ctrl[ 1 ];
	ctrl->ldctl_oid = LDAP_CONTROL_DUPENT_RESPONSE;
	ctrl->ldctl_iscritical = 0;
	ctrl->ldctl_value.bv_len = ctrlval.bv_len;
	AC_MEMCPY( ctrl->ldctl_value.bv_val, ctrlval.bv_val, ctrlval.bv_len );
	ctrl->ldctl_value.bv_val[ ctrl->ldctl_value.bv_len ] = '\0';

	ber_free_buf( ber );

	ctrlsp[0] = ctrl;
	ctrlsp[1] = NULL;
	slap_add_ctrls( op, rs, ctrlsp );

	return SLAP_CB_CONTINUE;
}
Esempio n. 5
0
/*
    4.2.2. Bind Response
    The Bind response is defined as follows.
    BindResponse ::= [APPLICATION 1] SEQUENCE {
    COMPONENTS OF LDAPResult,
    serverSaslCreds [7] OCTET STRING OPTIONAL }
 */
VOID
VmDirSendSASLBindResponse(
    PVDIR_OPERATION     pOperation
    )
{
    DWORD               dwError = 0;
    BerElementBuffer    berbuf;
    BerElement *        ber = (BerElement *) &berbuf;
    PVDIR_LDAP_RESULT   pResult = &(pOperation->ldapResult);
    ber_tag_t           respType = GetResultTag(pOperation->reqCode);

    (void) memset( (char *)&berbuf, '\0', sizeof( BerElementBuffer ));

    ber_init2( ber, NULL, LBER_USE_DER );

    VMDIR_LOG_INFO( LDAP_DEBUG_ARGS, "VmDirSendLdapResponse: code (%d), Error (%d)(%s)",
                    respType, pResult->errCode, VDIR_SAFE_STRING(pResult->pszErrMsg));

    dwError = ber_printf( ber, "{it{ess" /*"}}"*/,
                        pOperation->msgId,                  // message sequence id
                        GetResultTag(pOperation->reqCode),  // ldap response type
                        pResult->errCode,                   // ldap return code e.g. LDAP_SASL_CONNTINUE
                        pResult->matchedDn.lberbv.bv_len > 0 ? pResult->matchedDn.lberbv.bv_val : "",
                        VDIR_SAFE_STRING(pResult->pszErrMsg));   // error text detail
    BAIL_ON_LBER_ERROR(dwError);

    // Send back TAG and SASL reply blob
    // NOTE, not exactly sure if we ever need to send Tag but WITHOUT blob reply if blob is empty.
    //       but this should NOT happen in GSSAPI scenario.
    if ( pResult->replyInfo.type == REP_SASL
         &&
         pResult->replyInfo.replyData.bvSaslReply.lberbv.bv_len > 0
       )
    {
        dwError = ber_printf( ber, "tO",
                              LDAP_TAG_SASL_RES_CREDS,
                              &pResult->replyInfo.replyData.bvSaslReply.lberbv );
        BAIL_ON_LBER_ERROR(dwError);
    }

    dwError = ber_printf( ber, "N}N}" );
    BAIL_ON_LBER_ERROR(dwError);

    dwError = WriteBerOnSocket( pOperation->conn, ber );
    BAIL_ON_VMDIR_ERROR(dwError);

cleanup:

    ber_free_buf( ber );

    return;

error:

    VMDIR_LOG_ERROR( VMDIR_LOG_MASK_ALL, "lber error (%d)", dwError);
    goto cleanup;
}
Esempio n. 6
0
int
WritePagedSearchDoneControl(
    VDIR_OPERATION *     op,
    BerElement *    ber
    )
{
    int                 retVal = LDAP_OPERATIONS_ERROR;
    BerElementBuffer    ctrlValBerbuf;
    BerElement *        ctrlValBer = (BerElement *) &ctrlValBerbuf;
    VDIR_BERVALUE       bvCtrlVal = VDIR_BERVALUE_INIT;

    if (!op || !op->showPagedResultsCtrl)
    {
        retVal = LDAP_PROTOCOL_ERROR;
        BAIL_ON_VMDIR_ERROR( retVal );
    }

    if ( op->showPagedResultsCtrl)
    {
        VDIR_PAGED_RESULT_CONTROL_VALUE*    prCtrlVal = &op->showPagedResultsCtrl->value.pagedResultCtrlVal;
        VMDIR_LOG_DEBUG( LDAP_DEBUG_TRACE,
                "WritePagedSearchDoneControl: Paged Search Done Control Value: pageSize[%d] cookie[%s]",
                prCtrlVal->pageSize,
                prCtrlVal->cookie );

        (void) memset( (char *)&ctrlValBerbuf, '\0', sizeof( BerElementBuffer ));
        ber_init2( ctrlValBer, NULL, LBER_USE_DER );

        if (ber_printf( ctrlValBer, "{is}", 0, prCtrlVal->cookie) == -1 )
        {
            VMDIR_LOG_ERROR( VMDIR_LOG_MASK_ALL, "SendLdapResult: ber_printf (to print Paged Search Done Control ...) failed" );
            retVal = LDAP_OPERATIONS_ERROR;
            BAIL_ON_VMDIR_ERROR( retVal );
        }

        bvCtrlVal.lberbv.bv_val = ctrlValBer->ber_buf;
        bvCtrlVal.lberbv.bv_len = ctrlValBer->ber_ptr - ctrlValBer->ber_buf;

        if (ber_printf(ber, "t{{sO}}", LDAP_TAG_CONTROLS, LDAP_CONTROL_PAGEDRESULTS, &bvCtrlVal.lberbv ) == -1)
        {
            VMDIR_LOG_ERROR( VMDIR_LOG_MASK_ALL, "WritePagedSearchDoneControl: ber_printf (to print Search Done Control ...) failed" );
            retVal = LDAP_OPERATIONS_ERROR;
            BAIL_ON_VMDIR_ERROR( retVal );
        }
    }

    retVal = LDAP_SUCCESS;

cleanup:
    ber_free_buf( ctrlValBer );
    return retVal;

error:
    goto cleanup;
}
Esempio n. 7
0
static void
send_paged_response( 
	Operation	*op,
	SlapReply	*rs,
	ID		*lastid,
	int		tentries )
{
	LDAPControl	*ctrls[2];
	BerElementBuffer berbuf;
	BerElement	*ber = (BerElement *)&berbuf;
	PagedResultsCookie respcookie;
	struct berval cookie;

	Debug(LDAP_DEBUG_ARGS,
		"send_paged_response: lastid=0x%08lx nentries=%d\n", 
		lastid ? *lastid : 0, rs->sr_nentries, NULL );

	ctrls[1] = NULL;

	ber_init2( ber, NULL, LBER_USE_DER );

	if ( lastid ) {
		respcookie = ( PagedResultsCookie )(*lastid);
		cookie.bv_len = sizeof( respcookie );
		cookie.bv_val = (char *)&respcookie;

	} else {
		respcookie = ( PagedResultsCookie )0;
		BER_BVSTR( &cookie, "" );
	}

	op->o_conn->c_pagedresults_state.ps_cookie = respcookie;
	op->o_conn->c_pagedresults_state.ps_count =
		((PagedResultsState *)op->o_pagedresults_state)->ps_count +
		rs->sr_nentries;

	/* return size of 0 -- no estimate */
	ber_printf( ber, "{iO}", 0, &cookie ); 

	ctrls[0] = op->o_tmpalloc( sizeof(LDAPControl), op->o_tmpmemctx );
	if ( ber_flatten2( ber, &ctrls[0]->ldctl_value, 0 ) == -1 ) {
		goto done;
	}

	ctrls[0]->ldctl_oid = LDAP_CONTROL_PAGEDRESULTS;
	ctrls[0]->ldctl_iscritical = 0;

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

done:
	(void) ber_free_buf( ber );
}
Esempio n. 8
0
void
ber_free( BerElement *ber, int freebuf )
{
	if( ber == NULL ) {
		LDAP_MEMORY_DEBUG_ASSERT( ber != NULL );
		return;
	}

	if( freebuf ) ber_free_buf( ber );

	ber_memfree_x( (char *) ber, ber->ber_memctx );
}
Esempio n. 9
0
static int pack_pagedresult_response_control(
	Operation		*op,
	SlapReply		*rs,
	sort_op			*so,
	LDAPControl	**ctrlsp )
{
	LDAPControl			*ctrl;
	BerElementBuffer	berbuf;
	BerElement			*ber		= (BerElement *)&berbuf;
	PagedResultsCookie	resp_cookie;
	struct berval		cookie, bv;
	int					rc;

	ber_init2( ber, NULL, LBER_USE_DER );
	ber_set_option( ber, LBER_OPT_BER_MEMCTX, &op->o_tmpmemctx );

	if ( so->so_nentries > 0 ) {
		resp_cookie		= ( PagedResultsCookie )so->so_tree;
		cookie.bv_len	= sizeof( PagedResultsCookie );
		cookie.bv_val	= (char *)&resp_cookie;
	} else {
		resp_cookie		= ( PagedResultsCookie )0;
		BER_BVZERO( &cookie );
	}

	op->o_conn->c_pagedresults_state.ps_cookie = resp_cookie;
	op->o_conn->c_pagedresults_state.ps_count
		= ((PagedResultsState *)op->o_pagedresults_state)->ps_count
		  + rs->sr_nentries;

	rc = ber_printf( ber, "{iO}", so->so_nentries, &cookie );
	if ( rc != -1 ) {
		rc = ber_flatten2( ber, &bv, 0 );
	}

	if ( rc != -1 ) {
		ctrl = (LDAPControl *)op->o_tmpalloc( sizeof(LDAPControl)+
			bv.bv_len, op->o_tmpmemctx );
		ctrl->ldctl_oid			= LDAP_CONTROL_PAGEDRESULTS;
		ctrl->ldctl_iscritical	= 0;
		ctrl->ldctl_value.bv_val = (char *)(ctrl+1);
		ctrl->ldctl_value.bv_len = bv.bv_len;
		memcpy( ctrl->ldctl_value.bv_val, bv.bv_val, bv.bv_len );
		ctrlsp[0] = ctrl;
	} else {
		ctrlsp[0] = NULL;
		rs->sr_err = LDAP_OTHER;
	}

	ber_free_buf( ber );

	return rs->sr_err;
}
Esempio n. 10
0
/* Generates the LdapControl to be communicated to the client
   in the case of Strong Consistency Write task */
int
WriteConsistencyWriteDoneControl(
    VDIR_OPERATION *       pOp,
    BerElement *           pBer
    )
{
    int                 retVal = LDAP_OPERATIONS_ERROR;
    BerElementBuffer    ctrlValBerbuf;
    BerElement *        pCtrlValBer = (BerElement *) &ctrlValBerbuf;
    VDIR_BERVALUE       bvCtrlVal = VDIR_BERVALUE_INIT;
    DWORD               dwStatus = 0;
    PSTR                pControlsString = NULL;

    if (pOp == NULL || pBer == NULL)
    {
       VMDIR_LOG_ERROR(VMDIR_LOG_MASK_ALL, "WriteConsistencyWriteDoneControl: VDIR_OPERATION or BerElement is NULL failed");
       BAIL_ON_VMDIR_ERROR(retVal);
    }

    (void) memset((char *)&ctrlValBerbuf, '\0', sizeof(BerElementBuffer));
    ber_init2(pCtrlValBer, NULL, LBER_USE_DER);

    dwStatus = pOp->strongConsistencyWriteCtrl->value.scwDoneCtrlVal.status;
    pControlsString = pOp->strongConsistencyWriteCtrl->type;

    if (ber_printf(pCtrlValBer, "{i}", dwStatus) == -1)
    {
       VMDIR_LOG_ERROR(VMDIR_LOG_MASK_ALL, "WriteConsistencyWriteDoneControl: ber_printf (to print status...) failed");
       BAIL_ON_VMDIR_ERROR(retVal);
    }

    bvCtrlVal.lberbv.bv_val = pCtrlValBer->ber_buf;
    bvCtrlVal.lberbv.bv_len = pCtrlValBer->ber_ptr - pCtrlValBer->ber_buf;

    if (ber_printf(pBer, "t{{sO}}", LDAP_TAG_CONTROLS, pControlsString, &bvCtrlVal.lberbv) == -1)
    {
        VMDIR_LOG_ERROR(VMDIR_LOG_MASK_ALL, "WriteConsistencyWriteDoneControl: ber_printf (to print ldapControl...) failed");
	BAIL_ON_VMDIR_ERROR(retVal);
    }

    retVal = LDAP_SUCCESS;

cleanup:
    ber_free_buf(pCtrlValBer);
    return retVal;

error:
    VMDIR_LOG_ERROR(VMDIR_LOG_MASK_ALL, "WriteConsistencyWriteDoneControl: failed");
    goto cleanup;
}
Esempio n. 11
0
static int pack_vlv_response_control(
	Operation		*op,
	SlapReply		*rs,
	sort_op			*so,
	LDAPControl	**ctrlsp )
{
	LDAPControl			*ctrl;
	BerElementBuffer	berbuf;
	BerElement			*ber		= (BerElement *)&berbuf;
	struct berval		cookie, bv;
	int					rc;

	ber_init2( ber, NULL, LBER_USE_DER );
	ber_set_option( ber, LBER_OPT_BER_MEMCTX, &op->o_tmpmemctx );

	rc = ber_printf( ber, "{iie", so->so_vlv_target, so->so_nentries,
		so->so_vlv_rc );

	if ( rc != -1 && so->so_vcontext ) {
		cookie.bv_val = (char *)&so->so_vcontext;
		cookie.bv_len = sizeof(so->so_vcontext);
		rc = ber_printf( ber, "tO", LDAP_VLVCONTEXT_IDENTIFIER, &cookie );
	}

	if ( rc != -1 ) {
		rc = ber_printf( ber, "}" );
	}

	if ( rc != -1 ) {
		rc = ber_flatten2( ber, &bv, 0 );
	}

	if ( rc != -1 ) {
		ctrl = (LDAPControl *)op->o_tmpalloc( sizeof(LDAPControl)+
			bv.bv_len, op->o_tmpmemctx );
		ctrl->ldctl_oid			= LDAP_CONTROL_VLVRESPONSE;
		ctrl->ldctl_iscritical	= 0;
		ctrl->ldctl_value.bv_val = (char *)(ctrl+1);
		ctrl->ldctl_value.bv_len = bv.bv_len;
		memcpy( ctrl->ldctl_value.bv_val, bv.bv_val, bv.bv_len );
		ctrlsp[0] = ctrl;
	} else {
		ctrlsp[0] = NULL;
		rs->sr_err = LDAP_OTHER;
	}

	ber_free_buf( ber );

	return rs->sr_err;
}
Esempio n. 12
0
static int
send_ldap_controls( Operation *o, BerElement *ber, LDAPControl **c )
{
	int rc;

	if( c == NULL )
		return 0;

	rc = ber_printf( ber, "t{"/*}*/, LDAP_TAG_CONTROLS );
	if( rc == -1 ) return rc;

	for( ; *c != NULL; c++) {
		rc = send_ldap_control( ber, *c );
		if( rc == -1 ) return rc;
	}

#ifdef SLAP_CONTROL_X_SORTEDRESULTS
	/* this is a hack to avoid having to modify op->s_ctrls */
	if( o->o_sortedresults ) {
		BerElementBuffer berbuf;
		BerElement *sber = (BerElement *) &berbuf;
		LDAPControl sorted;
		BER_BVZERO( &sorted.ldctl_value );
		sorted.ldctl_oid = LDAP_CONTROL_SORTRESPONSE;
		sorted.ldctl_iscritical = 0;

		ber_init2( sber, NULL, LBER_USE_DER );

		ber_printf( sber, "{e}", LDAP_UNWILLING_TO_PERFORM );

		if( ber_flatten2( sber, &sorted.ldctl_value, 0 ) == -1 ) {
			return -1;
		}

		(void) ber_free_buf( sber );

		rc = send_ldap_control( ber, &sorted );
		if( rc == -1 ) return rc;
	}
#endif

	rc = ber_printf( ber, /*{*/"N}" );

	return rc;
}
Esempio n. 13
0
static int pack_sss_response_control(
	Operation		*op,
	SlapReply		*rs,
	LDAPControl	**ctrlsp )
{
	LDAPControl			*ctrl;
	BerElementBuffer	berbuf;
	BerElement			*ber		= (BerElement *)&berbuf;
	struct berval		bv;
	int					rc;

	ber_init2( ber, NULL, LBER_USE_DER );
	ber_set_option( ber, LBER_OPT_BER_MEMCTX, &op->o_tmpmemctx );

	/* Pack error code */
	rc = ber_printf(ber, "{e}", rs->sr_err);

	if ( rc != -1)
		rc = ber_flatten2( ber, &bv, 0 );

	if ( rc != -1 ) {
		ctrl = (LDAPControl *)op->o_tmpalloc( sizeof(LDAPControl)+
			bv.bv_len, op->o_tmpmemctx );
		ctrl->ldctl_oid			= LDAP_CONTROL_SORTRESPONSE;
		ctrl->ldctl_iscritical	= 0;
		ctrl->ldctl_value.bv_val = (char *)(ctrl+1);
		ctrl->ldctl_value.bv_len = bv.bv_len;
		memcpy( ctrl->ldctl_value.bv_val, bv.bv_val, bv.bv_len );
		ctrlsp[0] = ctrl;
	} else {
		ctrlsp[0] = NULL;
		rs->sr_err = LDAP_OTHER;
	}

	ber_free_buf( ber );

	return rs->sr_err;
}
Esempio n. 14
0
static int
deref_response( Operation *op, SlapReply *rs )
{
	int rc = SLAP_CB_CONTINUE;

	if ( rs->sr_type == REP_SEARCH ) {
		BerElementBuffer berbuf;
		BerElement *ber = (BerElement *) &berbuf;
		deref_cb_t *dc = (deref_cb_t *)op->o_callback->sc_private;
		DerefSpec *ds;
		DerefRes *dr, *drhead = NULL, **drp = &drhead;
		struct berval bv = BER_BVNULL;
		int nDerefRes = 0, nDerefVals = 0, nAttrs = 0, nVals = 0;
		struct berval ctrlval;
		LDAPControl *ctrl, *ctrlsp[2];
		AccessControlState acl_state = ACL_STATE_INIT;
		static char dummy = '\0';
		Entry *ebase;
		int i;

		rc = overlay_entry_get_ov( op, &rs->sr_entry->e_nname, NULL, NULL, 0, &ebase, dc->dc_on );
		if ( rc != LDAP_SUCCESS || ebase == NULL ) {
			return SLAP_CB_CONTINUE;
		}

		for ( ds = dc->dc_ds; ds; ds = ds->ds_next ) {
			Attribute *a = attr_find( ebase->e_attrs, ds->ds_derefAttr );

			if ( a != NULL ) {
				DerefVal *dv;
				BerVarray *bva;

				if ( !access_allowed( op, rs->sr_entry, a->a_desc,
						NULL, ACL_READ, &acl_state ) )
				{
					continue;
				}

				dr = op->o_tmpcalloc( 1,
					sizeof( DerefRes ) + ( sizeof( DerefVal ) + sizeof( BerVarray * ) * ds->ds_nattrs ) * ( a->a_numvals + 1 ),
					op->o_tmpmemctx );
				dr->dr_spec = *ds;
				dv = dr->dr_vals = (DerefVal *)&dr[ 1 ];
				bva = (BerVarray *)&dv[ a->a_numvals + 1 ];

				bv.bv_len += ds->ds_derefAttr->ad_cname.bv_len;
				nAttrs++;
				nDerefRes++;

				for ( i = 0; !BER_BVISNULL( &a->a_nvals[ i ] ); i++ ) {
					Entry *e = NULL;

					dv[ i ].dv_attrVals = bva;
					bva += ds->ds_nattrs;


					if ( !access_allowed( op, rs->sr_entry, a->a_desc,
							&a->a_nvals[ i ], ACL_READ, &acl_state ) )
					{
						dv[ i ].dv_derefSpecVal.bv_val = &dummy;
						continue;
					}

					ber_dupbv_x( &dv[ i ].dv_derefSpecVal, &a->a_vals[ i ], op->o_tmpmemctx );
					bv.bv_len += dv[ i ].dv_derefSpecVal.bv_len;
					nVals++;
					nDerefVals++;

					rc = overlay_entry_get_ov( op, &a->a_nvals[ i ], NULL, NULL, 0, &e, dc->dc_on );
					if ( rc == LDAP_SUCCESS && e != NULL ) {
						int j;

						if ( access_allowed( op, e, slap_schema.si_ad_entry,
							NULL, ACL_READ, NULL ) )
						{
							for ( j = 0; j < ds->ds_nattrs; j++ ) {
								Attribute *aa;

								if ( !access_allowed( op, e, ds->ds_attributes[ j ], NULL,
									ACL_READ, &acl_state ) )
								{
									continue;
								}

								aa = attr_find( e->e_attrs, ds->ds_attributes[ j ] );
								if ( aa != NULL ) {
									unsigned k, h, last = aa->a_numvals;

									ber_bvarray_dup_x( &dv[ i ].dv_attrVals[ j ],
										aa->a_vals, op->o_tmpmemctx );

									bv.bv_len += ds->ds_attributes[ j ]->ad_cname.bv_len;

									for ( k = 0, h = 0; k < aa->a_numvals; k++ ) {
										if ( !access_allowed( op, e,
											aa->a_desc,
											&aa->a_nvals[ k ],
											ACL_READ, &acl_state ) )
										{
											op->o_tmpfree( dv[ i ].dv_attrVals[ j ][ h ].bv_val,
												op->o_tmpmemctx );
											dv[ i ].dv_attrVals[ j ][ h ] = dv[ i ].dv_attrVals[ j ][ --last ];
											BER_BVZERO( &dv[ i ].dv_attrVals[ j ][ last ] );
											continue;
										}
										bv.bv_len += dv[ i ].dv_attrVals[ j ][ h ].bv_len;
										nVals++;
										h++;
									}
									nAttrs++;
								}
							}
						}

						overlay_entry_release_ov( op, e, 0, dc->dc_on );
					}
				}

				*drp = dr;
				drp = &dr->dr_next;
			}
		}
		overlay_entry_release_ov( op, ebase, 0, dc->dc_on );

		if ( drhead == NULL ) {
			return SLAP_CB_CONTINUE;
		}

		/* cook the control value */
		bv.bv_len += nVals * sizeof(struct berval)
			+ nAttrs * sizeof(struct berval)
			+ nDerefVals * sizeof(DerefVal)
			+ nDerefRes * sizeof(DerefRes);
		bv.bv_val = op->o_tmpalloc( bv.bv_len, op->o_tmpmemctx );

		ber_init2( ber, &bv, LBER_USE_DER );
		ber_set_option( ber, LBER_OPT_BER_MEMCTX, &op->o_tmpmemctx );

		rc = ber_printf( ber, "{" /*}*/ );
		for ( dr = drhead; dr != NULL; dr = dr->dr_next ) {
			for ( i = 0; !BER_BVISNULL( &dr->dr_vals[ i ].dv_derefSpecVal ); i++ ) {
				int j, first = 1;

				if ( dr->dr_vals[ i ].dv_derefSpecVal.bv_val == &dummy ) {
					continue;
				}

				rc = ber_printf( ber, "{OO" /*}*/,
					&dr->dr_spec.ds_derefAttr->ad_cname,
					&dr->dr_vals[ i ].dv_derefSpecVal );
				op->o_tmpfree( dr->dr_vals[ i ].dv_derefSpecVal.bv_val, op->o_tmpmemctx );
				for ( j = 0; j < dr->dr_spec.ds_nattrs; j++ ) {
					if ( dr->dr_vals[ i ].dv_attrVals[ j ] != NULL ) {
						if ( first ) {
							rc = ber_printf( ber, "t{" /*}*/,
								(LBER_CONSTRUCTED|LBER_CLASS_CONTEXT) );
							first = 0;
						}
						rc = ber_printf( ber, "{O[W]}",
							&dr->dr_spec.ds_attributes[ j ]->ad_cname,
							dr->dr_vals[ i ].dv_attrVals[ j ] );
						op->o_tmpfree( dr->dr_vals[ i ].dv_attrVals[ j ],
							op->o_tmpmemctx );
					}
				}
				if ( !first ) {
					rc = ber_printf( ber, /*{{*/ "}N}" );
				} else {
					rc = ber_printf( ber, /*{*/ "}" );
				}
			}
		}
		rc = ber_printf( ber, /*{*/ "}" );
		if ( ber_flatten2( ber, &ctrlval, 0 ) == -1 ) {
			if ( op->o_deref == SLAP_CONTROL_CRITICAL ) {
				rc = LDAP_CONSTRAINT_VIOLATION;

			} else {
				rc = SLAP_CB_CONTINUE;
			}
			goto cleanup;
		}

		ctrl = op->o_tmpcalloc( 1,
			sizeof( LDAPControl ) + ctrlval.bv_len + 1,
			op->o_tmpmemctx );
		ctrl->ldctl_value.bv_val = (char *)&ctrl[ 1 ];
		ctrl->ldctl_oid = LDAP_CONTROL_X_DEREF;
		ctrl->ldctl_iscritical = 0;
		ctrl->ldctl_value.bv_len = ctrlval.bv_len;
		memcpy( ctrl->ldctl_value.bv_val, ctrlval.bv_val, ctrlval.bv_len );
		ctrl->ldctl_value.bv_val[ ctrl->ldctl_value.bv_len ] = '\0';

		ber_free_buf( ber );

		ctrlsp[0] = ctrl;
		ctrlsp[1] = NULL;
		slap_add_ctrls( op, rs, ctrlsp );

		rc = SLAP_CB_CONTINUE;

cleanup:;
		/* release all */
		for ( ; drhead != NULL; ) {
			DerefRes *drnext = drhead->dr_next;
			op->o_tmpfree( drhead, op->o_tmpmemctx );
			drhead = drnext;
		}

	} else if ( rs->sr_type == REP_RESULT ) {
		rc = deref_cleanup( op, rs );
	}

	return rc;
}
Esempio n. 15
0
static int
dds_op_extended( Operation *op, SlapReply *rs )
{
	slap_overinst	*on = (slap_overinst *)op->o_bd->bd_info;
	dds_info_t	*di = on->on_bi.bi_private;

	if ( DDS_OFF( di ) ) {
		return SLAP_CB_CONTINUE;
	}

	if ( bvmatch( &op->ore_reqoid, &slap_EXOP_REFRESH ) ) {
		Entry		*e = NULL;
		time_t		ttl;
		BackendDB	db = *op->o_bd;
		SlapReply	rs2 = { REP_RESULT };
		Operation	op2 = *op;
		slap_callback	sc = { 0 };
		Modifications	ttlmod = { { 0 } };
		struct berval	ttlvalues[ 2 ];
		char		ttlbuf[STRLENOF("31557600") + 1];

		rs->sr_err = slap_parse_refresh( op->ore_reqdata, NULL, &ttl,
			&rs->sr_text, NULL );
		assert( rs->sr_err == LDAP_SUCCESS );

		if ( ttl <= 0 || ttl > DDS_RF2589_MAX_TTL ) {
			rs->sr_err = LDAP_PROTOCOL_ERROR;
			rs->sr_text = "invalid time-to-live for dynamicObject";
			return rs->sr_err;
		}

		if ( ttl > di->di_max_ttl ) {
			/* FIXME: I don't understand if this has to be an error,
			 * or an indication that the requested Ttl has been
			 * shortened to di->di_max_ttl >= 1 day */
			rs->sr_err = LDAP_SIZELIMIT_EXCEEDED;
			rs->sr_text = "time-to-live for dynamicObject exceeds limit";
			return rs->sr_err;
		}

		if ( di->di_min_ttl && ttl < di->di_min_ttl ) {
			ttl = di->di_min_ttl;
		}

		/* 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;
				}
				rs->sr_err = LDAP_REFERRAL;

			} else {
				rs->sr_text = "shadow context; no update referral";
				rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
			}

			return rs->sr_err;
		}

		assert( !BER_BVISNULL( &op->o_req_ndn ) );



		/* check if exists but not dynamicObject */
		op->o_bd->bd_info = (BackendInfo *)on->on_info;
		rs->sr_err = be_entry_get_rw( op, &op->o_req_ndn,
			slap_schema.si_oc_dynamicObject, NULL, 0, &e );
		if ( rs->sr_err != LDAP_SUCCESS ) {
			rs->sr_err = be_entry_get_rw( op, &op->o_req_ndn,
				NULL, NULL, 0, &e );
			if ( rs->sr_err == LDAP_SUCCESS && e != NULL ) {
				/* return referral only if "disclose"
				 * is granted on the object */
				if ( ! access_allowed( op, e,
						slap_schema.si_ad_entry,
						NULL, ACL_DISCLOSE, NULL ) )
				{
					rs->sr_err = LDAP_NO_SUCH_OBJECT;

				} else {
					rs->sr_err = LDAP_OBJECT_CLASS_VIOLATION;
					rs->sr_text = "refresh operation only applies to dynamic objects";
				}
				be_entry_release_r( op, e );

			} else {
				rs->sr_err = LDAP_NO_SUCH_OBJECT;
			}
			return rs->sr_err;

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

		/* we require manage privileges on the entryTtl,
		 * and fake a Relax control */
		op2.o_tag = LDAP_REQ_MODIFY;
		op2.o_bd = &db;
		db.bd_info = (BackendInfo *)on->on_info;
		op2.o_callback = &sc;
		sc.sc_response = slap_null_cb;
		op2.o_relax = SLAP_CONTROL_CRITICAL;
		op2.orm_modlist = &ttlmod;

		ttlmod.sml_op = LDAP_MOD_REPLACE;
		ttlmod.sml_flags = SLAP_MOD_MANAGING;
		ttlmod.sml_desc = slap_schema.si_ad_entryTtl;
		ttlmod.sml_values = ttlvalues;
		ttlmod.sml_numvals = 1;
		ttlvalues[ 0 ].bv_val = ttlbuf;
		ttlvalues[ 0 ].bv_len = snprintf( ttlbuf, sizeof( ttlbuf ), "%ld", ttl );
		BER_BVZERO( &ttlvalues[ 1 ] );

		/* the entryExpireTimestamp is added by modify */
		rs->sr_err = slap_biglock_call_be( op_modify, &op2, &rs2 );

		if ( ttlmod.sml_next != NULL ) {
			slap_mods_free( ttlmod.sml_next, 1 );
		}

		if ( rs->sr_err == LDAP_SUCCESS ) {
			int			rc;
			BerElementBuffer	berbuf;
			BerElement		*ber = (BerElement *)&berbuf;

			ber_init_w_nullc( ber, LBER_USE_DER );

			rc = ber_printf( ber, "{tiN}", LDAP_TAG_EXOP_REFRESH_RES_TTL, (int)ttl );

			if ( rc < 0 ) {
				rs->sr_err = LDAP_OTHER;
				rs->sr_text = "internal error";

			} else {
				(void)ber_flatten( ber, &rs->sr_rspdata );
				rs->sr_rspoid = ch_strdup( slap_EXOP_REFRESH.bv_val );

				Log3( LDAP_DEBUG_TRACE, LDAP_LEVEL_INFO,
					"%s REFRESH dn=\"%s\" TTL=%ld\n",
					op->o_log_prefix, op->o_req_ndn.bv_val, ttl );
			}

			ber_free_buf( ber );
		}

		return rs->sr_err;
	}

	return SLAP_CB_CONTINUE;
}
Esempio n. 16
0
int
VmDirSendSearchEntry(
   PVDIR_OPERATION     pOperation,
   PVDIR_ENTRY         pSrEntry
   )
{
    int                         retVal = LDAP_SUCCESS;
    BerElementBuffer            berbuf;
    BerElement *                ber = (BerElement *) &berbuf;
    BOOLEAN                     bFreeBer = FALSE;
    ber_len_t                   iBlobSize = 0;
    BerValue                    lberBervEntryBlob = {0};
    int                         nAttrs = 0;
    int                         nVals = 0;
    BOOLEAN                     attrMetaDataReqd = FALSE;
    SearchReq *                 sr = &(pOperation->request.searchReq);
    int                         i = 0;
    BOOLEAN                     nonTrivialAttrsInReplScope = FALSE;
    uint32_t                    iSearchReqSpecialChars = 0;
    PATTRIBUTE_META_DATA_NODE   pAttrMetaData = NULL;
    int                         numAttrMetaData = 0;
    PVDIR_ATTRIBUTE             pAttr = NULL;
    USN                         usnChanged = 0;
    PSTR                        pszLocalErrorMsg = NULL;

    if ( !pOperation || !pSrEntry )
    {
        retVal = ERROR_INVALID_PARAMETER;
        BAIL_ON_VMDIR_ERROR(retVal);
    }

    pSrEntry->bSearchEntrySent = FALSE;

    // see if client request has "*" and/or "+" ("-" for userpassword internal to vmdir)
    // WEI TODO: when we have attribute level ACL check, this information will be useful
    // return result will depend on ACL each on each attribute client is asking before
    // generating a final result to send back
    SetSpecialReturnChar(&pOperation->request.searchReq, &iSearchReqSpecialChars);

    if ( pSrEntry->eId == DSE_ROOT_ENTRY_ID
         &&
         pOperation->request.searchReq.attrs == NULL
       )
    {
        //  For ADSI, if no specific attributes requested of DSE ROOT search,
        //  return ALL (include operational) attributes.
        iSearchReqSpecialChars |= LDAP_SEARCH_REQUEST_CHAR_OP;
    }

    // ACL check before processing/sending the current srEntry back
    retVal = VmDirSrvAccessCheck( pOperation, &pOperation->conn->AccessInfo, pSrEntry, VMDIR_RIGHT_DS_READ_PROP );
    BAIL_ON_VMDIR_ERROR( retVal );

    if ( pOperation->opType == VDIR_OPERATION_TYPE_INTERNAL )
    {
        ; // no op in INTERNAL case
    }
    else
    {
        // If not replication, and showDeletedObjectsCtrl not present, => don't send back Deleted objects (tombstones).
        if (pOperation->syncReqCtrl == NULL && pOperation->showDeletedObjectsCtrl == NULL)
        {
            pAttr = VmDirEntryFindAttribute(ATTR_IS_DELETED, pSrEntry);
            if (pAttr)
            {
                if (VmDirStringCompareA((PSTR)pAttr->vals[0].lberbv.bv_val, VMDIR_IS_DELETED_TRUE_STR, FALSE) == 0)
                {
                    goto cleanup; // Don't send this entry
                }
            }
        }
        // In case of replication request, skip certain updates
        if (pOperation->syncReqCtrl != NULL)
        {
            PVDIR_ATTRIBUTE                 pAttrUsnCreated = NULL;
            USN                             usnCreated = 0;
            USN                             limitUsn = 0;
            VMDIR_REPLICATION_AGREEMENT *   replAgr = NULL;

            pAttr = VmDirEntryFindAttribute(ATTR_USN_CHANGED, pSrEntry);
            assert( pAttr != NULL );
            usnChanged = VmDirStringToLA( pAttr->vals[0].lberbv.bv_val, NULL, 10);

            // Check if usnChanged is beyond successful replication update state
            limitUsn = VmDirdGetLimitLocalUsnToBeSupplied();
            if (limitUsn != 0 && usnChanged >= limitUsn)
            {
                VMDIR_LOG_INFO(VMDIR_LOG_MASK_ALL, "SendSearchEntry: bug# 863244 RACE CONDITION encountered., "
                          "usnChanged = %ld, limitLocalUsnToBeSupplied = %ld, skipping entry: %s", usnChanged,
                          limitUsn, pSrEntry->dn.lberbv.bv_val );
                goto cleanup; // Don't send this entry
            }

            // Check if usnChanged is beyond lowestPendingUncommittedUsn recorded at the beginning of replication search

            if (pOperation->lowestPendingUncommittedUsn != 0 && usnChanged >= pOperation->lowestPendingUncommittedUsn)
            {
                VMDIR_LOG_INFO( LDAP_DEBUG_REPL, "SendSearchEntry: usnChanged = %ld, lowestPendingUncommittedUsn = %ld, "
                          "skipping entry: %s", usnChanged, pOperation->lowestPendingUncommittedUsn,
                          pSrEntry->dn.lberbv.bv_val );
                goto cleanup; // Don't send this entry
            }

            // Don't send (skip) modifications to my server object, and my RAs
            pAttrUsnCreated = VmDirEntryFindAttribute(ATTR_USN_CREATED, pSrEntry);
            assert( pAttrUsnCreated != NULL );
            usnCreated = VmDirStringToLA( pAttrUsnCreated->vals[0].lberbv.bv_val, NULL, 10);
            // Only send back creation of certain objects, and not their modifications.
            // Check if consumer has already seen the creation. If yes, we are dealing with mods, which should be skipped
            // for my server object, and my RAs
            // Note: Skipping mods for RAs and Server Objects will cause inconsistencies with replicas. But these
            // two types only have local scope regarding functional effects. But if we are looking up / processing
            // information for these two types of objects on a replica, we need to watch out for potential
            // inconsistencies against the original source.
            if (pOperation->syncReqCtrl->value.syncReqCtrlVal.intLastLocalUsnProcessed > usnCreated)
            {
                if (strcmp(pSrEntry->dn.bvnorm_val, gVmdirServerGlobals.serverObjDN.bvnorm_val) == 0)
                {
                    VMDIR_LOG_INFO( LDAP_DEBUG_REPL, "SendSearchEntry: Not sending modifications to my server object, DN: %s",
                              gVmdirServerGlobals.serverObjDN.lberbv.bv_val );
                    goto cleanup; // Don't send this entry
                }
                for (replAgr = gVmdirReplAgrs; replAgr != NULL; replAgr = replAgr->next )
                {
                    if (strcmp(pSrEntry->dn.bvnorm_val, replAgr->dn.bvnorm_val) == 0)
                    {
                        VMDIR_LOG_INFO( LDAP_DEBUG_REPL, "SendSearchEntry: Not sending modifications to my RA object, DN: %s",
                                  replAgr->dn.bvnorm_val );
                        goto cleanup; // Don't send this entry
                    }
                }
            }

            // do not replicate DSE Root entry, because it is a "local" entry.
            if (pSrEntry->eId == DSE_ROOT_ENTRY_ID)
            {
                VMDIR_LOG_INFO( LDAP_DEBUG_REPL, "SendSearchEntry: Not sending modifications to DSE Root entry, DN: %s",
                          pSrEntry->dn.bvnorm_val );
                goto cleanup; // Don't send this entry
            }

        }

        // Approximate calculation for the required ber size, because apart from lengths and strings, ber also includes
        // tags.
        if ( VmDirComputeEncodedEntrySize(pSrEntry, &nAttrs, &nVals, &iBlobSize) != 0
             ||
             VmDirAllocateMemory(iBlobSize, (PVOID*)&lberBervEntryBlob.bv_val) != 0
           )
        {
            retVal = LDAP_OPERATIONS_ERROR;
            BAIL_ON_VMDIR_ERROR_WITH_MSG(   retVal, (pszLocalErrorMsg), "no memory");
        }
        lberBervEntryBlob.bv_len = iBlobSize;

        ber_init2( ber, &lberBervEntryBlob, LBER_USE_DER );  // ber takes over lberBervEntryBlob.lberbv.bv_val ownership
        bFreeBer = TRUE;

        if ( ber_printf( ber, "{it{O{", pOperation->msgId, LDAP_RES_SEARCH_ENTRY, &pSrEntry->dn ) == -1)
        {
            VMDIR_LOG_ERROR( VMDIR_LOG_MASK_ALL, "SendSearchEntry: ber_printf (to print msgId ...) failed" );
            retVal = LDAP_OTHER;
            BAIL_ON_VMDIR_ERROR_WITH_MSG(   retVal, (pszLocalErrorMsg),
                                            "Encoding msgId, RES_SEARCH_ENTRY, DN failed");
        }
        // Determine if we need to send back the attribute metaData
        if ( pOperation->syncReqCtrl != NULL ) // Replication
        {
            attrMetaDataReqd = TRUE;
        }
        else // check if attrMetaData attribute has been requested explicitly.
        {
            if (sr->attrs != NULL)
            {
                for (i = 0; sr->attrs[i].lberbv.bv_val != NULL; i++)
                {
                    if (VmDirStringCompareA( sr->attrs[i].lberbv.bv_val, ATTR_ATTR_META_DATA, FALSE) == 0)
                    {
                        attrMetaDataReqd = TRUE;
                        break;
                    }
                }
            }
        }

        if (attrMetaDataReqd)
        {
            if ((pOperation->pBEIF->pfnBEGetAllAttrsMetaData( pOperation->pBECtx, pSrEntry->eId, &pAttrMetaData,
                                                              &numAttrMetaData )) != 0)
            {
                VMDIR_LOG_ERROR( VMDIR_LOG_MASK_ALL, "SendSearchEntry: pfnBEGetAllAttrsMetaData failed for entryId: %ld",
                                   pSrEntry->eId);
                retVal = LDAP_OPERATIONS_ERROR;
                BAIL_ON_VMDIR_ERROR_WITH_MSG(   retVal, (pszLocalErrorMsg),
                                                "pfnBEGetAllAttrsMetaData failed.");
            }

            // SJ-TBD: Following double for loop to be optimized
            // Copy attrMetaData to corresponding attributes
            for (i=0; i<numAttrMetaData; i++)
            {
                for ( pAttr = pSrEntry->attrs; pAttr != NULL; pAttr = pAttr->next)
                {
                    if (pAttr->pATDesc->usAttrID == pAttrMetaData[i].attrID)
                    {
                        VmDirStringCpyA( pAttr->metaData, VMDIR_MAX_ATTR_META_DATA_LEN, pAttrMetaData[i].metaData );
                        pAttrMetaData[i].metaData[0] = '\0';
                    }
                }
            }
        }

        retVal = WriteAttributes( pOperation, pSrEntry, iSearchReqSpecialChars , ber, &pszLocalErrorMsg );
        BAIL_ON_VMDIR_ERROR( retVal );

        if (attrMetaDataReqd)
        {
            retVal = WriteMetaDataAttribute( pOperation, pSrEntry->attrs, numAttrMetaData, pAttrMetaData, ber,
                                             &nonTrivialAttrsInReplScope, &pszLocalErrorMsg );
            BAIL_ON_VMDIR_ERROR( retVal );
        }

        if (ber_printf( ber, "N}N}" ) == -1)
        {
            VMDIR_LOG_ERROR( VMDIR_LOG_MASK_ALL,
                      "ber_printf (to terminate the entry and the complete search result entry message ...) failed" );
            retVal = LDAP_OTHER;
            BAIL_ON_VMDIR_ERROR_WITH_MSG(   retVal, (pszLocalErrorMsg),
                                            "Encoding terminating the entry failed.");
        }

        if ( pOperation->syncReqCtrl != NULL ) // Replication, => write Sync State Control
        {
            retVal = WriteSyncStateControl( pOperation, pSrEntry->attrs, ber, &pszLocalErrorMsg );
            BAIL_ON_VMDIR_ERROR( retVal );
        }

        if (ber_printf( ber, "N}" ) == -1)
        {
            VMDIR_LOG_ERROR( VMDIR_LOG_MASK_ALL,
                      "ber_printf (to terminate the entry and the complete search result entry message ...) failed" );;
            retVal = LDAP_OTHER;
            BAIL_ON_VMDIR_ERROR_WITH_MSG(   retVal, (pszLocalErrorMsg),
                                            "Encoding terminating the entry failed.");
        }

        if ((pOperation->syncReqCtrl == NULL) || (pOperation->syncReqCtrl != NULL && nonTrivialAttrsInReplScope ))
        {
            if (WriteBerOnSocket( pOperation->conn, ber ) != 0)
            {
                VMDIR_LOG_ERROR( VMDIR_LOG_MASK_ALL, "SendSearchEntry: WriteBerOnSocket failed." );
                retVal = LDAP_UNAVAILABLE;
                BAIL_ON_VMDIR_ERROR( retVal );
            }

            pSrEntry->bSearchEntrySent = TRUE;
            sr->iNumEntrySent++;

            VMDIR_LOG_INFO( LDAP_DEBUG_REPL, "SendSearchEntry: Send entry: %s", pSrEntry->dn.lberbv.bv_val);
        }
        else
        {
            VMDIR_LOG_INFO( LDAP_DEBUG_REPL, "SendSearchEntry: NOT Sending entry: %s %p %d",
                            pSrEntry->dn.lberbv.bv_val, pOperation->syncReqCtrl, nonTrivialAttrsInReplScope);
        }

        // record max local usnChanged in syncControlDone
        if (pOperation->syncReqCtrl != NULL)
        {
            if (usnChanged  > pOperation->syncDoneCtrl->value.syncDoneCtrlVal.intLastLocalUsnProcessed)
            {
                pOperation->syncDoneCtrl->value.syncDoneCtrlVal.intLastLocalUsnProcessed = usnChanged;
            }
        }

        retVal = LDAP_SUCCESS;
    }

cleanup:
    if (bFreeBer)
    {
        ber_free_buf( ber );
    }
    VMDIR_SAFE_FREE_MEMORY( pAttrMetaData );
    VMDIR_SAFE_FREE_MEMORY(pszLocalErrorMsg);

    return( retVal );

error:

    VMDIR_LOG_ERROR( VMDIR_LOG_MASK_ALL,
                     "SendSearchEntry failed DN=(%s), (%u)(%s)",
                     (pSrEntry && pSrEntry->dn.lberbv.bv_val) ? pSrEntry->dn.lberbv.bv_val : "",
                     retVal, VDIR_SAFE_STRING( pszLocalErrorMsg));

    if ( !pOperation->ldapResult.pszErrMsg && pszLocalErrorMsg )
    {
        pOperation->ldapResult.pszErrMsg = pszLocalErrorMsg;
        pszLocalErrorMsg = NULL;
    }

    goto cleanup;
}
Esempio n. 17
0
void
VmDirSendLdapResult(
   VDIR_OPERATION * op
   )
{
   BerElementBuffer berbuf;
   BerElement *     ber = (BerElement *) &berbuf;
   ber_int_t        msgId = 0;
   ber_tag_t        resCode = 0;
   size_t           iNumSearchEntrySent = 0;
   PCSTR            pszSocketInfo = NULL;

   (void) memset( (char *)&berbuf, '\0', sizeof( BerElementBuffer ));

   resCode = GetResultTag( op->reqCode );
   msgId = (resCode != LBER_SEQUENCE) ? op->msgId : 0;

   if ( resCode == LDAP_RES_SEARCH_RESULT )
   {
       iNumSearchEntrySent = op->request.searchReq.iNumEntrySent;
   }

   ber_init2( ber, NULL, LBER_USE_DER );

   if (op->conn)
   {
      pszSocketInfo = op->conn->szClientIP;
   }

   if (op->ldapResult.errCode &&
       op->ldapResult.errCode != LDAP_SASL_BIND_IN_PROGRESS)
   {
       VMDIR_LOG_ERROR(
          VMDIR_LOG_MASK_ALL,
          "VmDirSendLdapResult: Request (%d), Error (%d), Message (%s), (%u) socket (%s)",
          op->reqCode,
          op->ldapResult.errCode,
          VDIR_SAFE_STRING(op->ldapResult.pszErrMsg),
          iNumSearchEntrySent,
          VDIR_SAFE_STRING(pszSocketInfo));
   }
   else if ( op->reqCode == LDAP_REQ_SEARCH )
   {
       VMDIR_LOG_INFO(
          LDAP_DEBUG_ARGS,
          "VmDirSendLdapResult: Request (%d), Error (%d), Message (%s), (%u) socket (%s)",
          op->reqCode,
          op->ldapResult.errCode,
          VDIR_SAFE_STRING(op->ldapResult.pszErrMsg),
          iNumSearchEntrySent,
          VDIR_SAFE_STRING(pszSocketInfo));
   }

   if (ber_printf( ber, "{it{essN}", msgId, resCode, op->ldapResult.errCode, "",
                       VDIR_SAFE_STRING(op->ldapResult.pszErrMsg)) == -1)
   {
      VMDIR_LOG_ERROR( VMDIR_LOG_MASK_ALL, "SendLdapResult: ber_printf (to print msgId ...) failed" );
      goto done;
   }

   // If Search, Replication, and one or more entries were sent back => Send back Sync Done Control
   if ( op->reqCode == LDAP_REQ_SEARCH && op->syncReqCtrl != NULL && op->syncDoneCtrl != NULL)
   {
       if (WriteSyncDoneControl( op, ber ) != LDAP_SUCCESS)
       {
           goto done;
       }
   }

   if ( op->reqCode == LDAP_REQ_SEARCH && op->showPagedResultsCtrl != NULL)
   {
       if (WritePagedSearchDoneControl( op, ber ) != LDAP_SUCCESS)
       {
           goto done;
       }
   }

   if (ber_printf( ber, "N}" ) == -1)
   {
      VMDIR_LOG_ERROR( VMDIR_LOG_MASK_ALL, "SendLdapResult: ber_printf (to print msgId ...) failed" );
      goto done;
   }

   if (WriteBerOnSocket( op->conn, ber ) != 0)
   {
      VMDIR_LOG_ERROR( VMDIR_LOG_MASK_ALL, "SendLdapResult: WriteBerOnSocket failed" );
      goto done;
   }

done:
   ber_free_buf( ber );

}
Esempio n. 18
0
int
WriteSyncStateControl(
   VDIR_OPERATION *   op,
   VDIR_ATTRIBUTE *   pAttr,
   BerElement *       ber,
   PSTR*              ppszErrorMsg
   )
{
    int                 retVal = LDAP_SUCCESS;
    VDIR_BERVALUE       syncStateCtrlType = {
                            {VmDirStringLenA( LDAP_CONTROL_SYNC_STATE ), LDAP_CONTROL_SYNC_STATE}, 0, 0, NULL };
    int                 entryState = LDAP_SYNC_MODIFY;
    BerElementBuffer    ctrlValBerbuf;
    BerElement *        ctrlValBer = (BerElement *) &ctrlValBerbuf;
    VDIR_BERVALUE       bvCtrlVal = VDIR_BERVALUE_INIT;
    PSTR                pszLocalErrorMsg = NULL;

    VMDIR_LOG_DEBUG( LDAP_DEBUG_TRACE, "WriteSyncStateControl: Begin" );

    /* Logic to determine the entry state is:
     *  Default entry state is LDAP_SYNC_MODIFY
     *
     *  If ATTR_USN_CREATED value is greater than the last local USN that the consumer has seen so far,
     *  entry state is LDAP_SYNC_ADD.
     *  Otherwise, if isDeleted=TRUE is in the replication scope, entry state is LDAP_SYNC_DELETE.
     *
     *  NOTE: The logic is based on the things (entry state + what has the consumer seen so far) seen by the supplier
     *  at this point in time. Things/state could be different at the time when consumer tries to apply this change.
     *  => may lead to various conflict resolution scenarios.
     */

    for ( ; pAttr != NULL; pAttr = pAttr->next)
    {
        if (pAttr->metaData[0] != '\0') // We are sending back this attribute's meta data. => Attribute is in
                                        // replication scope. SJ-TBD: we are overloading pAttr->metaData
                                        // field. Should we have another field (e.g. inReplScope) in Attribute
        {
            if ( VmDirStringCompareA( pAttr->type.lberbv.bv_val, ATTR_IS_DELETED, FALSE ) == 0 &&
                 VmDirStringCompareA( pAttr->vals[0].lberbv.bv_val, VMDIR_IS_DELETED_TRUE_STR, FALSE ) == 0)
            {
                entryState = LDAP_SYNC_DELETE;
                continue; // Look if it is LDAP_SYNC_ADD case
            }

            if (VmDirStringCompareA( pAttr->type.lberbv.bv_val, ATTR_USN_CREATED, FALSE ) == 0)
            {
                entryState = LDAP_SYNC_ADD;
                break;
            }
        }
    }

    if (ber_printf( ber, "t{{O", LDAP_TAG_CONTROLS, &(syncStateCtrlType.lberbv) ) == -1 )
    {
        VMDIR_LOG_ERROR(VMDIR_LOG_MASK_ALL, "WriteSyncStateControl: ber_printf (to print attribute name ...) failed" );
        retVal = LDAP_OPERATIONS_ERROR;
        BAIL_ON_VMDIR_ERROR_WITH_MSG(   retVal, (pszLocalErrorMsg),
                                        "Encoding sync state control failed.");
    }

    ////////// Build ber for the control value

    (void) memset( (char *)&ctrlValBerbuf, '\0', sizeof( BerElementBuffer ));
    ber_init2( ctrlValBer, NULL, LBER_USE_DER );

    if (ber_printf( ctrlValBer, "{i}", entryState ) == -1 )
    {
        VMDIR_LOG_ERROR( VMDIR_LOG_MASK_ALL, "SendLdapResult: ber_printf (to print Sync Done Control ...) failed" );
        retVal = LDAP_OPERATIONS_ERROR;
        BAIL_ON_VMDIR_ERROR_WITH_MSG(   retVal, (pszLocalErrorMsg),
                                        "Encoding sync state control failed.");
    }

    ////////////// Building ber for the control value done

    bvCtrlVal.lberbv.bv_val = ctrlValBer->ber_buf;
    bvCtrlVal.lberbv.bv_len = ctrlValBer->ber_ptr - ctrlValBer->ber_buf;

    if (ber_printf( ber, "O", &bvCtrlVal.lberbv ) == -1 )
    {
        VMDIR_LOG_ERROR( VMDIR_LOG_MASK_ALL, "SendLdapResult: ber_printf (to print Sync Done Control ...) failed" );
        retVal = LDAP_OPERATIONS_ERROR;
        BAIL_ON_VMDIR_ERROR_WITH_MSG(   retVal, (pszLocalErrorMsg),
                                        "Encoding sync state control failed.");
    }

    if (ber_printf( ber, "}}" ) == -1 )
    {
        VMDIR_LOG_ERROR( VMDIR_LOG_MASK_ALL, "SendLdapResult: ber_printf (to print Sync Done Control ...) failed" );
        retVal = LDAP_OPERATIONS_ERROR;
        BAIL_ON_VMDIR_ERROR_WITH_MSG(retVal, (pszLocalErrorMsg),
                                     "Encoding sync state control failed.");
    }

cleanup:
    ber_free_buf( ctrlValBer );

    if (ppszErrorMsg)
    {
        *ppszErrorMsg = pszLocalErrorMsg;
    }
    else
    {
        VMDIR_SAFE_FREE_MEMORY(pszLocalErrorMsg);
    }

    VMDIR_LOG_DEBUG( LDAP_DEBUG_TRACE, "WriteSyncStateControl: End" );

    return( retVal );

error:

    goto cleanup;
}
Esempio n. 19
0
static int
null_back_respond( Operation *op, SlapReply *rs, int rc )
{
	LDAPControl ctrl[SLAP_MAX_RESPONSE_CONTROLS], *ctrls[SLAP_MAX_RESPONSE_CONTROLS];
	int c = 0;

	BerElementBuffer	ps_berbuf;
	BerElement		*ps_ber = NULL;
	LDAPControl		**preread_ctrl = NULL,
				**postread_ctrl = NULL;

	rs->sr_err = LDAP_OTHER;

	/* this comes first, as in case of assertion failure
	 * any further processing must stop */
	if ( get_assert( op ) ) {
		rs->sr_err = LDAP_ASSERTION_FAILED;
		goto respond;
	}

	if ( op->o_preread ) {
		Entry		e = { 0 };

		switch ( op->o_tag ) {
		case LDAP_REQ_MODIFY:
		case LDAP_REQ_RENAME:
		case LDAP_REQ_DELETE:
			e.e_name = op->o_req_dn;
			e.e_nname = op->o_req_ndn;

			preread_ctrl = &ctrls[c];
			*preread_ctrl = NULL;

			if ( slap_read_controls( op, rs, &e,
				&slap_pre_read_bv, preread_ctrl ) )
			{
				preread_ctrl = NULL;

				Debug( LDAP_DEBUG_TRACE,
					"<=- null_back_respond: pre-read "
					"failed!\n", 0, 0, 0 );

				if ( op->o_preread & SLAP_CONTROL_CRITICAL ) {
					/* FIXME: is it correct to abort
					 * operation if control fails? */
					goto respond;
				}

			} else {
				c++;
			}
			break;
		}
	}

	if ( op->o_postread ) {
		Entry		e = { 0 };

		switch ( op->o_tag ) {
		case LDAP_REQ_ADD:
		case LDAP_REQ_MODIFY:
		case LDAP_REQ_RENAME:
			if ( op->o_tag == LDAP_REQ_ADD ) {
				e.e_name = op->ora_e->e_name;
				e.e_nname = op->ora_e->e_nname;

			} else {
				e.e_name = op->o_req_dn;
				e.e_nname = op->o_req_ndn;
			}

			postread_ctrl = &ctrls[c];
			*postread_ctrl = NULL;

			if ( slap_read_controls( op, rs, &e,
				&slap_post_read_bv, postread_ctrl ) )
			{
				postread_ctrl = NULL;

				Debug( LDAP_DEBUG_TRACE,
					"<=- null_back_respond: post-read "
					"failed!\n", 0, 0, 0 );

				if ( op->o_postread & SLAP_CONTROL_CRITICAL ) {
					/* FIXME: is it correct to abort
					 * operation if control fails? */
					goto respond;
				}

			} else {
				c++;
			}
			break;
		}
	}

	if ( op->o_noop ) {
		switch ( op->o_tag ) {
		case LDAP_REQ_ADD:
		case LDAP_REQ_MODIFY:
		case LDAP_REQ_RENAME:
		case LDAP_REQ_DELETE:
		case LDAP_REQ_EXTENDED:
			rc = LDAP_X_NO_OPERATION;
			break;
		}
	}

	if ( get_pagedresults( op ) > SLAP_CONTROL_IGNORED ) {
		struct berval		cookie = BER_BVC( "" );

		/* should not be here... */
		assert( op->o_tag == LDAP_REQ_SEARCH );

		ctrl[c].ldctl_oid = LDAP_CONTROL_PAGEDRESULTS;
		ctrl[c].ldctl_iscritical = 0;

		ps_ber = (BerElement *)&ps_berbuf;
		ber_init2( ps_ber, NULL, LBER_USE_DER );

		/* return size of 0 -- no estimate */
		ber_printf( ps_ber, "{iO}", 0, &cookie ); 

		if ( ber_flatten2( ps_ber, &ctrl[c].ldctl_value, 0 ) == -1 ) {
			goto done;
		}
		
		ctrls[c] = &ctrl[c];
		c++;
	}

	/* terminate controls array */
	ctrls[c] = NULL;
	rs->sr_ctrls = ctrls;
	rs->sr_err = rc;

respond:;
	send_ldap_result( op, rs );
	rs->sr_ctrls = NULL;

done:;
	if ( ps_ber != NULL ) {
		(void) ber_free_buf( ps_ber );
	}

	if( preread_ctrl != NULL && (*preread_ctrl) != NULL ) {
		slap_sl_free( (*preread_ctrl)->ldctl_value.bv_val, op->o_tmpmemctx );
		slap_sl_free( *preread_ctrl, op->o_tmpmemctx );
	}

	if( postread_ctrl != NULL && (*postread_ctrl) != NULL ) {
		slap_sl_free( (*postread_ctrl)->ldctl_value.bv_val, op->o_tmpmemctx );
		slap_sl_free( *postread_ctrl, op->o_tmpmemctx );
	}

	return rs->sr_err;
}
Esempio n. 20
0
int
slap_send_search_entry( Operation *op, SlapReply *rs )
{
	BerElementBuffer berbuf;
	BerElement	*ber = (BerElement *) &berbuf;
	Attribute	*a;
	int		i, j, rc = LDAP_UNAVAILABLE, bytes;
	int		userattrs;
	AccessControlState acl_state = ACL_STATE_INIT;
	int			 attrsonly;
	AttributeDescription *ad_entry = slap_schema.si_ad_entry;

	/* a_flags: array of flags telling if the i-th element will be
	 *          returned or filtered out
	 * e_flags: array of a_flags
	 */
	char **e_flags = NULL;

	rs->sr_type = REP_SEARCH;

	if ( op->ors_slimit >= 0 && rs->sr_nentries >= op->ors_slimit ) {
		rc = LDAP_SIZELIMIT_EXCEEDED;
		goto error_return;
	}

	/* Every 64 entries, check for thread pool pause */
	if ( ( ( rs->sr_nentries & 0x3f ) == 0x3f ) &&
		ldap_pvt_thread_pool_pausing( &connection_pool ) > 0 )
	{
		rc = LDAP_BUSY;
		goto error_return;
	}

	/* eventually will loop through generated operational attribute types
	 * currently implemented types include:
	 *	entryDN, subschemaSubentry, and hasSubordinates */
	/* NOTE: moved before overlays callback circling because
	 * they may modify entry and other stuff in rs */
	/* check for special all operational attributes ("+") type */
	/* FIXME: maybe we could set this flag at the operation level;
	 * however, in principle the caller of send_search_entry() may
	 * change the attribute list at each call */
	rs->sr_attr_flags = slap_attr_flags( rs->sr_attrs );

	rc = backend_operational( op, rs );
	if ( rc ) {
		goto error_return;
	}

	if ( op->o_callback ) {
		rc = slap_response_play( op, rs );
		if ( rc != SLAP_CB_CONTINUE ) {
			goto error_return;
		}
	}

	Debug( LDAP_DEBUG_TRACE, "=> send_search_entry: conn %lu dn=\"%s\"%s\n",
		op->o_connid, rs->sr_entry->e_name.bv_val,
		op->ors_attrsonly ? " (attrsOnly)" : "" );

	attrsonly = op->ors_attrsonly;

	if ( !access_allowed( op, rs->sr_entry, ad_entry, NULL, ACL_READ, NULL )) {
		Debug( LDAP_DEBUG_ACL,
			"send_search_entry: conn %lu access to entry (%s) not allowed\n",
			op->o_connid, rs->sr_entry->e_name.bv_val );

		rc = LDAP_INSUFFICIENT_ACCESS;
		goto error_return;
	}

	if ( op->o_res_ber ) {
		/* read back control or LDAP_CONNECTIONLESS */
	    ber = op->o_res_ber;
	} else {
		struct berval	bv;

		bv.bv_len = entry_flatsize( rs->sr_entry, 0 );
		bv.bv_val = op->o_tmpalloc( bv.bv_len, op->o_tmpmemctx );

		ber_init2( ber, &bv, LBER_USE_DER );
		ber_set_option( ber, LBER_OPT_BER_MEMCTX, &op->o_tmpmemctx );
	}

#ifdef LDAP_CONNECTIONLESS
	if ( op->o_conn && op->o_conn->c_is_udp ) {
		/* CONNECTIONLESS */
		if ( op->o_protocol == LDAP_VERSION2 ) {
	    	rc = ber_printf(ber, "t{O{" /*}}*/,
				LDAP_RES_SEARCH_ENTRY, &rs->sr_entry->e_name );
		} else {
	    	rc = ber_printf( ber, "{it{O{" /*}}}*/, op->o_msgid,
				LDAP_RES_SEARCH_ENTRY, &rs->sr_entry->e_name );
		}
	} else
#endif
	if ( op->o_res_ber ) {
		/* read back control */
	    rc = ber_printf( ber, "t{O{" /*}}*/,
			LDAP_RES_SEARCH_ENTRY, &rs->sr_entry->e_name );
	} else {
	    rc = ber_printf( ber, "{it{O{" /*}}}*/, op->o_msgid,
			LDAP_RES_SEARCH_ENTRY, &rs->sr_entry->e_name );
	}

	if ( rc == -1 ) {
		Debug( LDAP_DEBUG_ANY,
			"send_search_entry: conn %lu  ber_printf failed\n",
			op->o_connid );

		if ( op->o_res_ber == NULL ) ber_free_buf( ber );
		set_ldap_error( rs, LDAP_OTHER, "encoding DN error" );
		rc = rs->sr_err;
		goto error_return;
	}

	/* check for special all user attributes ("*") type */
	userattrs = SLAP_USERATTRS( rs->sr_attr_flags );

	/* create an array of arrays of flags. Each flag corresponds
	 * to particular value of attribute and equals 1 if value matches
	 * to ValuesReturnFilter or 0 if not
	 */
	if ( op->o_vrFilter != NULL ) {
		int	k = 0;
		size_t	size;

		for ( a = rs->sr_entry->e_attrs, i=0; a != NULL; a = a->a_next, i++ ) {
			for ( j = 0; a->a_vals[j].bv_val != NULL; j++ ) k++;
		}

		size = i * sizeof(char *) + k;
		if ( size > 0 ) {
			char	*a_flags;
			e_flags = slap_sl_calloc ( 1, i * sizeof(char *) + k, op->o_tmpmemctx );
			if( e_flags == NULL ) {
		    	Debug( LDAP_DEBUG_ANY,
					"send_search_entry: conn %lu slap_sl_calloc failed\n",
					op->o_connid );
				ber_free( ber, 1 );

				set_ldap_error( rs, LDAP_OTHER, "out of memory" );
				goto error_return;
			}
			a_flags = (char *)(e_flags + i);
			memset( a_flags, 0, k );
			for ( a=rs->sr_entry->e_attrs, i=0; a != NULL; a=a->a_next, i++ ) {
				for ( j = 0; a->a_vals[j].bv_val != NULL; j++ );
				e_flags[i] = a_flags;
				a_flags += j;
			}

			rc = filter_matched_values(op, rs->sr_entry->e_attrs, &e_flags) ;
			if ( rc == -1 ) {
			    	Debug( LDAP_DEBUG_ANY, "send_search_entry: "
					"conn %lu matched values filtering failed\n",
					op->o_connid );
				if ( op->o_res_ber == NULL ) ber_free_buf( ber );
				set_ldap_error( rs, LDAP_OTHER,
					"matched values filtering error" );
				rc = rs->sr_err;
				goto error_return;
			}
		}
	}

	for ( a = rs->sr_entry->e_attrs, j = 0; a != NULL; a = a->a_next, j++ ) {
		AttributeDescription *desc = a->a_desc;
		int finish = 0;

		if ( rs->sr_attrs == NULL ) {
			/* all user attrs request, skip operational attributes */
			if( is_at_operational( desc->ad_type ) ) {
				continue;
			}

		} else {
			/* specific attrs requested */
			if ( is_at_operational( desc->ad_type ) ) {
				/* if not explicitly requested */
				if ( !ad_inlist( desc, rs->sr_attrs )) {
					/* if not all op attrs requested, skip */
					if ( !SLAP_OPATTRS( rs->sr_attr_flags ))
						continue;
					/* if DSA-specific and replicating, skip */
					if ( op->o_sync != SLAP_CONTROL_NONE &&
						desc->ad_type->sat_usage == LDAP_SCHEMA_DSA_OPERATION )
						continue;
				}
			} else {
				if ( !userattrs && !ad_inlist( desc, rs->sr_attrs ) ) {
					continue;
				}
			}
		}

		if ( attrsonly ) {
			if ( ! access_allowed( op, rs->sr_entry, desc, NULL,
				ACL_READ, &acl_state ) )
			{
				Debug( LDAP_DEBUG_ACL, "send_search_entry: "
					"conn %lu access to attribute %s not allowed\n",
				        op->o_connid, desc->ad_cname.bv_val );
				continue;
			}

			if (( rc = ber_printf( ber, "{O[" /*]}*/ , &desc->ad_cname )) == -1 ) {
				Debug( LDAP_DEBUG_ANY,
					"send_search_entry: conn %lu  ber_printf failed\n",
					op->o_connid );

				if ( op->o_res_ber == NULL ) ber_free_buf( ber );
				set_ldap_error( rs, LDAP_OTHER,
					"encoding description error");
				rc = rs->sr_err;
				goto error_return;
			}
			finish = 1;

		} else {
			int first = 1;
			for ( i = 0; a->a_nvals[i].bv_val != NULL; i++ ) {
				if ( ! access_allowed( op, rs->sr_entry,
					desc, &a->a_nvals[i], ACL_READ, &acl_state ) )
				{
					Debug( LDAP_DEBUG_ACL,
						"send_search_entry: conn %lu "
						"access to attribute %s, value #%d not allowed\n",
						op->o_connid, desc->ad_cname.bv_val, i );

					continue;
				}

				if ( op->o_vrFilter && e_flags[j][i] == 0 ){
					continue;
				}

				if ( first ) {
					first = 0;
					finish = 1;
					if (( rc = ber_printf( ber, "{O[" /*]}*/ , &desc->ad_cname )) == -1 ) {
						Debug( LDAP_DEBUG_ANY,
							"send_search_entry: conn %lu  ber_printf failed\n",
							op->o_connid );

						if ( op->o_res_ber == NULL ) ber_free_buf( ber );
						set_ldap_error( rs, LDAP_OTHER,
							"encoding description error");
						rc = rs->sr_err;
						goto error_return;
					}
				}
				if (( rc = ber_printf( ber, "O", &a->a_vals[i] )) == -1 ) {
					Debug( LDAP_DEBUG_ANY,
						"send_search_entry: conn %lu  "
						"ber_printf failed.\n", op->o_connid );

					if ( op->o_res_ber == NULL ) ber_free_buf( ber );
					set_ldap_error( rs, LDAP_OTHER,
						"encoding values error" );
					rc = rs->sr_err;
					goto error_return;
				}
			}
		}

		if ( finish && ( rc = ber_printf( ber, /*{[*/ "]N}" )) == -1 ) {
			Debug( LDAP_DEBUG_ANY,
				"send_search_entry: conn %lu ber_printf failed\n",
				op->o_connid );

			if ( op->o_res_ber == NULL ) ber_free_buf( ber );
			set_ldap_error( rs, LDAP_OTHER, "encode end error" );
			rc = rs->sr_err;
			goto error_return;
		}
	}

	/* NOTE: moved before overlays callback circling because
	 * they may modify entry and other stuff in rs */
	if ( rs->sr_operational_attrs != NULL && op->o_vrFilter != NULL ) {
		int	k = 0;
		size_t	size;

		for ( a = rs->sr_operational_attrs, i=0; a != NULL; a = a->a_next, i++ ) {
			for ( j = 0; a->a_vals[j].bv_val != NULL; j++ ) k++;
		}

		size = i * sizeof(char *) + k;
		if ( size > 0 ) {
			char	*a_flags, **tmp;

			/*
			 * Reuse previous memory - we likely need less space
			 * for operational attributes
			 */
			tmp = slap_sl_realloc( e_flags, i * sizeof(char *) + k,
				op->o_tmpmemctx );
			if ( tmp == NULL ) {
			    	Debug( LDAP_DEBUG_ANY,
					"send_search_entry: conn %lu "
					"not enough memory "
					"for matched values filtering\n",
					op->o_connid );
				if ( op->o_res_ber == NULL ) ber_free_buf( ber );
				set_ldap_error( rs, LDAP_OTHER,
					"not enough memory for matched values filtering" );
				goto error_return;
			}
			e_flags = tmp;
			a_flags = (char *)(e_flags + i);
			memset( a_flags, 0, k );
			for ( a = rs->sr_operational_attrs, i=0; a != NULL; a = a->a_next, i++ ) {
				for ( j = 0; a->a_vals[j].bv_val != NULL; j++ );
				e_flags[i] = a_flags;
				a_flags += j;
			}
			rc = filter_matched_values(op, rs->sr_operational_attrs, &e_flags) ;

			if ( rc == -1 ) {
			    	Debug( LDAP_DEBUG_ANY,
					"send_search_entry: conn %lu "
					"matched values filtering failed\n",
					op->o_connid);
				if ( op->o_res_ber == NULL ) ber_free_buf( ber );
				set_ldap_error( rs, LDAP_OTHER,
					"matched values filtering error" );
				rc = rs->sr_err;
				goto error_return;
			}
		}
	}

	for (a = rs->sr_operational_attrs, j=0; a != NULL; a = a->a_next, j++ ) {
		AttributeDescription *desc = a->a_desc;

		if ( rs->sr_attrs == NULL ) {
			/* all user attrs request, skip operational attributes */
			if( is_at_operational( desc->ad_type ) ) {
				continue;
			}

		} else {
			/* specific attrs requested */
			if( is_at_operational( desc->ad_type ) ) {
				if ( !SLAP_OPATTRS( rs->sr_attr_flags ) &&
					!ad_inlist( desc, rs->sr_attrs ) )
				{
					continue;
				}
				/* if DSA-specific and replicating, skip */
				if ( op->o_sync != SLAP_CONTROL_NONE &&
					desc->ad_type->sat_usage == LDAP_SCHEMA_DSA_OPERATION )
					continue;
			} else {
				if ( !userattrs && !ad_inlist( desc, rs->sr_attrs ) ) {
					continue;
				}
			}
		}

		if ( ! access_allowed( op, rs->sr_entry, desc, NULL,
			ACL_READ, &acl_state ) )
		{
			Debug( LDAP_DEBUG_ACL,
				"send_search_entry: conn %lu "
				"access to attribute %s not allowed\n",
				op->o_connid, desc->ad_cname.bv_val );

			continue;
		}

		rc = ber_printf( ber, "{O[" /*]}*/ , &desc->ad_cname );
		if ( rc == -1 ) {
			Debug( LDAP_DEBUG_ANY,
				"send_search_entry: conn %lu  "
				"ber_printf failed\n", op->o_connid );

			if ( op->o_res_ber == NULL ) ber_free_buf( ber );
			set_ldap_error( rs, LDAP_OTHER,
				"encoding description error" );
			rc = rs->sr_err;
			goto error_return;
		}

		if ( ! attrsonly ) {
			for ( i = 0; a->a_vals[i].bv_val != NULL; i++ ) {
				if ( ! access_allowed( op, rs->sr_entry,
					desc, &a->a_vals[i], ACL_READ, &acl_state ) )
				{
					Debug( LDAP_DEBUG_ACL,
						"send_search_entry: conn %lu "
						"access to %s, value %d not allowed\n",
						op->o_connid, desc->ad_cname.bv_val, i );

					continue;
				}

				if ( op->o_vrFilter && e_flags[j][i] == 0 ){
					continue;
				}

				if (( rc = ber_printf( ber, "O", &a->a_vals[i] )) == -1 ) {
					Debug( LDAP_DEBUG_ANY,
						"send_search_entry: conn %lu  ber_printf failed\n",
						op->o_connid );

					if ( op->o_res_ber == NULL ) ber_free_buf( ber );
					set_ldap_error( rs, LDAP_OTHER,
						"encoding values error" );
					rc = rs->sr_err;
					goto error_return;
				}
			}
		}

		if (( rc = ber_printf( ber, /*{[*/ "]N}" )) == -1 ) {
			Debug( LDAP_DEBUG_ANY,
				"send_search_entry: conn %lu  ber_printf failed\n",
				op->o_connid );

			if ( op->o_res_ber == NULL ) ber_free_buf( ber );
			set_ldap_error( rs, LDAP_OTHER, "encode end error" );
			rc = rs->sr_err;
			goto error_return;
		}
	}

	/* free e_flags */
	if ( e_flags ) {
		slap_sl_free( e_flags, op->o_tmpmemctx );
		e_flags = NULL;
	}

	rc = ber_printf( ber, /*{{*/ "}N}" );

	if( rc != -1 ) {
		rc = send_ldap_controls( op, ber, rs->sr_ctrls );
	}

	if( rc != -1 ) {
#ifdef LDAP_CONNECTIONLESS
		if( op->o_conn && op->o_conn->c_is_udp ) {
			if ( op->o_protocol != LDAP_VERSION2 ) {
				rc = ber_printf( ber, /*{*/ "N}" );
			}
		} else
#endif
		if ( op->o_res_ber == NULL ) {
			rc = ber_printf( ber, /*{*/ "N}" );
		}
	}

	if ( rc == -1 ) {
		Debug( LDAP_DEBUG_ANY, "ber_printf failed\n" );

		if ( op->o_res_ber == NULL ) ber_free_buf( ber );
		set_ldap_error( rs, LDAP_OTHER, "encode entry end error" );
		rc = rs->sr_err;
		goto error_return;
	}

	Statslog( LDAP_DEBUG_STATS2, "%s ENTRY dn=\"%s\"\n",
	    op->o_log_prefix, rs->sr_entry->e_nname.bv_val );

	rs_flush_entry( op, rs, NULL );

	if ( op->o_res_ber == NULL ) {
		bytes = send_ldap_ber( op, ber );
		ber_free_buf( ber );

		if ( bytes < 0 ) {
			Debug( LDAP_DEBUG_ANY,
				"send_search_entry: conn %lu  ber write failed.\n",
				op->o_connid );

			rc = LDAP_UNAVAILABLE;
			goto error_return;
		}
		rs->sr_nentries++;

		ldap_pvt_thread_mutex_lock( &op->o_counters->sc_mutex );
		ldap_pvt_mp_add_ulong( op->o_counters->sc_bytes, (unsigned long)bytes );
		ldap_pvt_mp_add_ulong( op->o_counters->sc_entries, 1 );
		ldap_pvt_mp_add_ulong( op->o_counters->sc_pdu, 1 );
		ldap_pvt_thread_mutex_unlock( &op->o_counters->sc_mutex );
	}

	Debug( LDAP_DEBUG_TRACE,
		"<= send_search_entry: conn %lu exit.\n", op->o_connid );

	rc = LDAP_SUCCESS;

error_return:;
	if ( op->o_callback ) {
		(void)slap_cleanup_play( op, rs );
	}

	if ( e_flags ) {
		slap_sl_free( e_flags, op->o_tmpmemctx );
	}

	/* FIXME: Can break if rs now contains an extended response */
	if ( rs->sr_operational_attrs ) {
		attrs_free( rs->sr_operational_attrs );
		rs->sr_operational_attrs = NULL;
	}
	rs->sr_attr_flags = SLAP_ATTRS_UNDEFINED;

	if ( op->o_tag == LDAP_REQ_SEARCH && rs->sr_type == REP_SEARCH ) {
		rs_flush_entry( op, rs, NULL );
	} else {
		RS_ASSERT( (rs->sr_flags & REP_ENTRY_MASK) == 0 );
	}

	if ( rs->sr_flags & REP_CTRLS_MUSTBEFREED ) {
		rs->sr_flags ^= REP_CTRLS_MUSTBEFREED; /* paranoia */
		if ( rs->sr_ctrls ) {
			slap_free_ctrls( op, rs->sr_ctrls );
			rs->sr_ctrls = NULL;
		}
	}

	return( rc );
}
Esempio n. 21
0
void
VmDirSendLdapReferralResult(
   VDIR_OPERATION * op,
   PCSTR pszRefSuffix,
   PBOOLEAN pbRefSent
   )
{
   DWORD dwError = 0;
   BerElementBuffer berbuf;
   BerElement *     ber = (BerElement *) &berbuf;
   ber_int_t        msgId = 0;
   PCSTR            pszSocketInfo = NULL;
   PSTR             pszLeader = NULL;
   PSTR             pszRef = NULL;
   PVDIR_BERVALUE   pBerv = NULL;
   BOOLEAN          bIsLdaps = FALSE;

   *pbRefSent = FALSE;
   (void) memset( (char *)&berbuf, '\0', sizeof( BerElementBuffer ));

   msgId = op->msgId;

   ber_init2( ber, NULL, LBER_USE_DER );

   if (op->conn)
   {
      pszSocketInfo = op->conn->szClientIP;
   }

   dwError = VmDirRaftGetLeader(&pszLeader);
   BAIL_ON_VMDIR_ERROR(dwError);
   
   if (pszLeader == NULL)
   {
       //server self is a raft leader or leader cannot determined (e.g. in voting stage).
       goto done;
   }

   if (op->conn->dwServerPort == VmDirGetLdapsPort())
   {
       bIsLdaps = TRUE;
   }

   dwError = VmDirAllocateStringPrintf(&pszRef, "%s://%s/%s",
               bIsLdaps ? "ldaps":"ldap",
               pszLeader,
               pszRefSuffix );
   BAIL_ON_VMDIR_ERROR(dwError);

   op->ldapResult.errCode = 0;
   if ((op->reqCode == LDAP_REQ_SEARCH && gVmdirGlobals.dwEnableRaftReferral & VMDIR_RAFT_SEARCH_REFERRAL_ERROR_CODE) ||
       ((op->reqCode == LDAP_REQ_ADD || op->reqCode == LDAP_REQ_DELETE ||
         op->reqCode == LDAP_REQ_MODIFY || op->reqCode == LDAP_REQ_MODDN) &&
         gVmdirGlobals.dwEnableRaftReferral & VMDIR_RAFT_ENABLE_UPDATE_ERROR_CODE))
   {
       op->ldapResult.errCode = LDAP_REFERRAL;
   }

   dwError = VmDirAllocateMemory( sizeof(VDIR_BERVALUE) * 2, (PVOID*)&pBerv);
   BAIL_ON_VMDIR_ERROR(dwError);

   pBerv[0].lberbv_len = VmDirStringLenA(pszRef);
   pBerv[0].lberbv_val = pszRef;
   pBerv[0].bOwnBvVal = TRUE;
   pBerv[1].lberbv_val = NULL;
   pBerv[1].lberbv_len = 0;

   dwError = ber_printf(ber, "{it{W}N}{it{ess}N}", msgId, LDAP_RES_SEARCH_REFERENCE, pBerv,
                        msgId, GetResultTag(op->reqCode), op->ldapResult.errCode, "", "");
   BAIL_ON_LBER_ERROR(dwError);

   dwError = WriteBerOnSocket( op->conn, ber );
   BAIL_ON_VMDIR_ERROR(dwError);

   *pbRefSent = TRUE;

   VMDIR_LOG_INFO(VMDIR_LOG_MASK_ALL, "VmDirSendLdapReferralResult: sent with referral %s", pszRef);

done:
   ber_free_buf( ber );
   VmDirFreeBervalArrayContent(pBerv, 1);
   VMDIR_SAFE_FREE_MEMORY(pBerv);
   VMDIR_SAFE_FREE_MEMORY(pszLeader);
   return;

error:
   goto done;
}
Esempio n. 22
0
File: vc.c Progetto: Joywar/openldap
static int
vc_create_response(
	void *conn,
	int resultCode,
	const char *diagnosticMessage,
	struct berval *servercred,
	struct berval *authzid,
	LDAPControl **ctrls,
	struct berval **val )
{
	BerElementBuffer berbuf;
	BerElement *ber = (BerElement *)&berbuf;
	struct berval bv;
	int rc;

	assert( val != NULL );

	*val = NULL;

	ber_init2( ber, NULL, LBER_USE_DER );

	(void)ber_printf( ber, "{is" /*}*/ , resultCode, diagnosticMessage ? diagnosticMessage : "" );

	if ( conn ) {
		struct berval cookie;

		cookie.bv_len = sizeof( conn );
		cookie.bv_val = (char *)&conn;
		(void)ber_printf( ber, "tO", 0, LDAP_TAG_EXOP_VERIFY_CREDENTIALS_COOKIE, &cookie ); 
	}

	if ( servercred ) {
		ber_printf( ber, "tO", LDAP_TAG_EXOP_VERIFY_CREDENTIALS_SCREDS, servercred ); 
	}

#if 0
	if ( authzid ) {
		ber_printf( ber, "tO", LDAP_TAG_EXOP_VERIFY_CREDENTIALS_AUTHZID, authzid ); 
	}
#endif

	if ( ctrls ) {
		int c;

		rc = ber_printf( ber, "t{"/*}*/, LDAP_TAG_EXOP_VERIFY_CREDENTIALS_CONTROLS );
		if ( rc == -1 ) goto done;

		for ( c = 0; ctrls[c] != NULL; c++ ) {
			rc = ber_printf( ber, "{s" /*}*/, ctrls[c]->ldctl_oid );

			if ( ctrls[c]->ldctl_iscritical ) {
				rc = ber_printf( ber, "b", (ber_int_t)ctrls[c]->ldctl_iscritical ) ;
				if ( rc == -1 ) goto done;
			}

			if ( ctrls[c]->ldctl_value.bv_val != NULL ) {
				rc = ber_printf( ber, "O", &ctrls[c]->ldctl_value ); 
				if( rc == -1 ) goto done;
			}

			rc = ber_printf( ber, /*{*/"N}" );
			if ( rc == -1 ) goto done;
		}

		rc = ber_printf( ber, /*{*/"N}" );
		if ( rc == -1 ) goto done;
	}

	ber_printf( ber, /*{*/ "}" );

	rc = ber_flatten2( ber, &bv, 0 );

	*val = ber_bvdup( &bv );

done:;
	ber_free_buf( ber );

	return rc;
}
Esempio n. 23
0
int
slap_send_search_reference( Operation *op, SlapReply *rs )
{
	BerElementBuffer berbuf;
	BerElement	*ber = (BerElement *) &berbuf;
	int rc = 0;
	int bytes;
	char *edn = rs->sr_entry ? rs->sr_entry->e_name.bv_val : "(null)";

	AttributeDescription *ad_ref = slap_schema.si_ad_ref;
	AttributeDescription *ad_entry = slap_schema.si_ad_entry;

	rs->sr_type = REP_SEARCHREF;
	if ( op->o_callback ) {
		rc = slap_response_play( op, rs );
		if ( rc != SLAP_CB_CONTINUE ) {
			goto rel;
		}
	}

	Debug( LDAP_DEBUG_TRACE,
		"=> send_search_reference: dn=\"%s\"\n",
		edn );

	if (  rs->sr_entry && ! access_allowed( op, rs->sr_entry,
		ad_entry, NULL, ACL_READ, NULL ) )
	{
		Debug( LDAP_DEBUG_ACL,
			"send_search_reference: access to entry not allowed\n" );
		rc = 1;
		goto rel;
	}

	if ( rs->sr_entry && ! access_allowed( op, rs->sr_entry,
		ad_ref, NULL, ACL_READ, NULL ) )
	{
		Debug( LDAP_DEBUG_ACL,
			"send_search_reference: access "
			"to reference not allowed\n" );
		rc = 1;
		goto rel;
	}

	if( op->o_domain_scope ) {
		Debug( LDAP_DEBUG_ANY,
			"send_search_reference: domainScope control in (%s)\n",
			edn );
		rc = 0;
		goto rel;
	}

	if( rs->sr_ref == NULL ) {
		Debug( LDAP_DEBUG_ANY,
			"send_search_reference: null ref in (%s)\n",
			edn );
		rc = 1;
		goto rel;
	}

	if( op->o_protocol < LDAP_VERSION3 ) {
		rc = 0;
		/* save the references for the result */
		if( rs->sr_ref[0].bv_val != NULL ) {
			if( value_add( &rs->sr_v2ref, rs->sr_ref ) )
				rc = LDAP_OTHER;
		}
		goto rel;
	}

#ifdef LDAP_CONNECTIONLESS
	if( op->o_conn && op->o_conn->c_is_udp ) {
		ber = op->o_res_ber;
	} else
#endif
	{
		ber_init_w_nullc( ber, LBER_USE_DER );
		ber_set_option( ber, LBER_OPT_BER_MEMCTX, &op->o_tmpmemctx );
	}

	rc = ber_printf( ber, "{it{W}" /*"}"*/ , op->o_msgid,
		LDAP_RES_SEARCH_REFERENCE, rs->sr_ref );

	if( rc != -1 ) {
		rc = send_ldap_controls( op, ber, rs->sr_ctrls );
	}

	if( rc != -1 ) {
		rc = ber_printf( ber, /*"{"*/ "N}" );
	}

	if ( rc == -1 ) {
		Debug( LDAP_DEBUG_ANY,
			"send_search_reference: ber_printf failed\n" );

#ifdef LDAP_CONNECTIONLESS
		if (!op->o_conn || op->o_conn->c_is_udp == 0)
#endif
		ber_free_buf( ber );
		set_ldap_error( rs, LDAP_OTHER, "encode DN error" );
		goto rel;
	}

	rc = 0;
	rs_flush_entry( op, rs, NULL );

#ifdef LDAP_CONNECTIONLESS
	if (!op->o_conn || op->o_conn->c_is_udp == 0) {
#endif
	bytes = send_ldap_ber( op, ber );
	ber_free_buf( ber );

	if ( bytes < 0 ) {
		rc = LDAP_UNAVAILABLE;
	} else {
		ldap_pvt_thread_mutex_lock( &op->o_counters->sc_mutex );
		ldap_pvt_mp_add_ulong( op->o_counters->sc_bytes, (unsigned long)bytes );
		ldap_pvt_mp_add_ulong( op->o_counters->sc_refs, 1 );
		ldap_pvt_mp_add_ulong( op->o_counters->sc_pdu, 1 );
		ldap_pvt_thread_mutex_unlock( &op->o_counters->sc_mutex );
	}
#ifdef LDAP_CONNECTIONLESS
	}
#endif
	if ( rs->sr_ref != NULL ) {
		int	r;

		for ( r = 0; !BER_BVISNULL( &rs->sr_ref[ r ] ); r++ ) {
			Statslog( LDAP_DEBUG_STATS2, "%s REF #%d \"%s\"\n",
				op->o_log_prefix, r, rs->sr_ref[0].bv_val );
		}

	} else {
		Statslog( LDAP_DEBUG_STATS2, "%s REF \"(null)\"\n",
			op->o_log_prefix );
	}

	Debug( LDAP_DEBUG_TRACE, "<= send_search_reference\n" );

	if ( 0 ) {
rel:
	    rs_flush_entry( op, rs, NULL );
	}

	if ( op->o_callback ) {
		(void)slap_cleanup_play( op, rs );
	}

	if ( rs->sr_flags & REP_CTRLS_MUSTBEFREED ) {
		rs->sr_flags ^= REP_CTRLS_MUSTBEFREED; /* paranoia */
		if ( rs->sr_ctrls ) {
			slap_free_ctrls( op, rs->sr_ctrls );
			rs->sr_ctrls = NULL;
		}
	}

	return rc;
}
Esempio n. 24
0
static int
send_ldap_response(
	Operation *op,
	SlapReply *rs )
{
	BerElementBuffer berbuf;
	BerElement	*ber = (BerElement *) &berbuf;
	int		rc = LDAP_SUCCESS;
	long	bytes;

	/* op was actually aborted, bypass everything if client didn't Cancel */
	if (( rs->sr_err == SLAPD_ABANDON ) && !op->o_cancel ) {
		rc = SLAPD_ABANDON;
		goto clean2;
	}

	if ( op->o_callback ) {
		rc = slap_response_play( op, rs );
		if ( rc != SLAP_CB_CONTINUE ) {
			goto clean2;
		}
	}

	/* op completed, connection aborted, bypass sending response */
	if ( op->o_abandon && !op->o_cancel ) {
		rc = SLAPD_ABANDON;
		goto clean2;
	}

#ifdef LDAP_CONNECTIONLESS
	if (op->o_conn && op->o_conn->c_is_udp)
		ber = op->o_res_ber;
	else
#endif
	{
		ber_init_w_nullc( ber, LBER_USE_DER );
		ber_set_option( ber, LBER_OPT_BER_MEMCTX, &op->o_tmpmemctx );
	}

	rc = rs->sr_err;
	if ( rc == SLAPD_ABANDON && op->o_cancel )
		rc = LDAP_CANCELLED;

	Debug( LDAP_DEBUG_TRACE,
		"send_ldap_response: msgid=%d tag=%lu err=%d\n",
		rs->sr_msgid, rs->sr_tag, rc );

	if( rs->sr_ref ) {
		Debug( LDAP_DEBUG_ARGS, "send_ldap_response: ref=\"%s\"\n",
			rs->sr_ref[0].bv_val ? rs->sr_ref[0].bv_val : "NULL" );
	}

#ifdef LDAP_CONNECTIONLESS
	if (op->o_conn && op->o_conn->c_is_udp &&
		op->o_protocol == LDAP_VERSION2 )
	{
		rc = ber_printf( ber, "t{ess" /*"}"*/,
			rs->sr_tag, rc,
		rs->sr_matched == NULL ? "" : rs->sr_matched,
		rs->sr_text == NULL ? "" : rs->sr_text );
	} else
#endif
	if ( rs->sr_type == REP_INTERMEDIATE ) {
	    rc = ber_printf( ber, "{it{" /*"}}"*/,
			rs->sr_msgid, rs->sr_tag );

	} else {
	    rc = ber_printf( ber, "{it{ess" /*"}}"*/,
		rs->sr_msgid, rs->sr_tag, rc,
		rs->sr_matched == NULL ? "" : rs->sr_matched,
		rs->sr_text == NULL ? "" : rs->sr_text );
	}

	if( rc != -1 ) {
		if ( rs->sr_ref != NULL ) {
			assert( rs->sr_err == LDAP_REFERRAL );
			rc = ber_printf( ber, "t{W}",
				LDAP_TAG_REFERRAL, rs->sr_ref );
		} else {
			assert( rs->sr_err != LDAP_REFERRAL );
		}
	}

	if( rc != -1 && rs->sr_type == REP_SASL && rs->sr_sasldata != NULL ) {
		rc = ber_printf( ber, "tO",
			LDAP_TAG_SASL_RES_CREDS, rs->sr_sasldata );
	}

	if( rc != -1 &&
		( rs->sr_type == REP_EXTENDED || rs->sr_type == REP_INTERMEDIATE ))
	{
		if ( rs->sr_rspoid != NULL ) {
			rc = ber_printf( ber, "ts",
				rs->sr_type == REP_EXTENDED
					? LDAP_TAG_EXOP_RES_OID : LDAP_TAG_IM_RES_OID,
				rs->sr_rspoid );
		}
		if( rc != -1 && rs->sr_rspdata != NULL ) {
			rc = ber_printf( ber, "tO",
				rs->sr_type == REP_EXTENDED
					? LDAP_TAG_EXOP_RES_VALUE : LDAP_TAG_IM_RES_VALUE,
				rs->sr_rspdata );
		}
	}

	if( rc != -1 ) {
		rc = ber_printf( ber, /*"{"*/ "N}" );
	}

	if( rc != -1 ) {
		rc = send_ldap_controls( op, ber, rs->sr_ctrls );
	}

	if( rc != -1 ) {
		rc = ber_printf( ber, /*"{"*/ "N}" );
	}

#ifdef LDAP_CONNECTIONLESS
	if( op->o_conn && op->o_conn->c_is_udp && op->o_protocol == LDAP_VERSION2
		&& rc != -1 )
	{
		rc = ber_printf( ber, /*"{"*/ "N}" );
	}
#endif

	if ( rc == -1 ) {
		Debug( LDAP_DEBUG_ANY, "ber_printf failed\n" );

#ifdef LDAP_CONNECTIONLESS
		if (!op->o_conn || op->o_conn->c_is_udp == 0)
#endif
		{
			ber_free_buf( ber );
		}
		goto cleanup;
	}

	/* send BER */
	bytes = send_ldap_ber( op, ber );
#ifdef LDAP_CONNECTIONLESS
	if (!op->o_conn || op->o_conn->c_is_udp == 0)
#endif
	{
		ber_free_buf( ber );
	}

	if ( bytes < 0 ) {
		Debug( LDAP_DEBUG_ANY,
			"send_ldap_response: ber write failed\n" );

		goto cleanup;
	}

	ldap_pvt_thread_mutex_lock( &op->o_counters->sc_mutex );
	ldap_pvt_mp_add_ulong( op->o_counters->sc_pdu, 1 );
	ldap_pvt_mp_add_ulong( op->o_counters->sc_bytes, (unsigned long)bytes );
	ldap_pvt_thread_mutex_unlock( &op->o_counters->sc_mutex );

cleanup:;
	/* Tell caller that we did this for real, as opposed to being
	 * overridden by a callback
	 */
	rc = SLAP_CB_CONTINUE;

clean2:;
	if ( op->o_callback ) {
		(void)slap_cleanup_play( op, rs );
	}

	if ( rs->sr_flags & REP_MATCHED_MUSTBEFREED ) {
		rs->sr_flags ^= REP_MATCHED_MUSTBEFREED; /* paranoia */
		if ( rs->sr_matched ) {
			free( (char *)rs->sr_matched );
			rs->sr_matched = NULL;
		}
	}

	if ( rs->sr_flags & REP_REF_MUSTBEFREED ) {
		rs->sr_flags ^= REP_REF_MUSTBEFREED; /* paranoia */
		if ( rs->sr_ref ) {
			ber_bvarray_free( rs->sr_ref );
			rs->sr_ref = NULL;
		}
	}

	if ( rs->sr_flags & REP_CTRLS_MUSTBEFREED ) {
		rs->sr_flags ^= REP_CTRLS_MUSTBEFREED; /* paranoia */
		if ( rs->sr_ctrls ) {
			slap_free_ctrls( op, rs->sr_ctrls );
			rs->sr_ctrls = NULL;
		}
	}

	return rc;
}
Esempio n. 25
0
meta_search_candidate_t
asyncmeta_back_search_start(
				Operation *op,
				SlapReply *rs,
			    a_metaconn_t *mc,
			    bm_context_t *bc,
			    int candidate,
			    struct berval		*prcookie,
			    ber_int_t		prsize )
{
	SlapReply		*candidates = bc->candidates;
	a_metainfo_t		*mi = ( a_metainfo_t * )mc->mc_info;
	a_metatarget_t		*mt = mi->mi_targets[ candidate ];
	a_metasingleconn_t	*msc = &mc->mc_conns[ candidate ];
	a_dncookie		dc;
	struct berval		realbase = op->o_req_dn;
	int			realscope = op->ors_scope;
	struct berval		mbase = BER_BVNULL;
	struct berval		mfilter = BER_BVNULL;
	char			**mapped_attrs = NULL;
	int			rc;
	meta_search_candidate_t	retcode;
	int timelimit;
	int			nretries = 1;
	LDAPControl		**ctrls = NULL;
	BerElement *ber;
	ber_int_t	msgid;
#ifdef SLAPD_META_CLIENT_PR
	LDAPControl		**save_ctrls = NULL;
#endif /* SLAPD_META_CLIENT_PR */

	/* this should not happen; just in case... */
	if ( msc->msc_ld == NULL ) {
		Debug( LDAP_DEBUG_ANY,
			"%s: asyncmeta_back_search_start candidate=%d ld=NULL%s.\n",
			op->o_log_prefix, candidate,
			META_BACK_ONERR_STOP( mi ) ? "" : " (ignored)" );
		candidates[ candidate ].sr_err = LDAP_OTHER;
		if ( META_BACK_ONERR_STOP( mi ) ) {
			return META_SEARCH_ERR;
		}
		candidates[ candidate ].sr_msgid = META_MSGID_IGNORE;
		return META_SEARCH_NOT_CANDIDATE;
	}

	Debug( LDAP_DEBUG_TRACE, "%s >>> asyncmeta_back_search_start[%d]\n", op->o_log_prefix, candidate, 0 );
	/*
	 * modifies the base according to the scope, if required
	 */
	if ( mt->mt_nsuffix.bv_len > op->o_req_ndn.bv_len ) {
		switch ( op->ors_scope ) {
		case LDAP_SCOPE_SUBTREE:
			/*
			 * make the target suffix the new base
			 * FIXME: this is very forgiving, because
			 * "illegal" searchBases may be turned
			 * into the suffix of the target; however,
			 * the requested searchBase already passed
			 * thru the candidate analyzer...
			 */
			if ( dnIsSuffix( &mt->mt_nsuffix, &op->o_req_ndn ) ) {
				realbase = mt->mt_nsuffix;
				if ( mt->mt_scope == LDAP_SCOPE_SUBORDINATE ) {
					realscope = LDAP_SCOPE_SUBORDINATE;
				}

			} else {
				/*
				 * this target is no longer candidate
				 */
				retcode = META_SEARCH_NOT_CANDIDATE;
				goto doreturn;
			}
			break;

		case LDAP_SCOPE_SUBORDINATE:
		case LDAP_SCOPE_ONELEVEL:
		{
			struct berval	rdn = mt->mt_nsuffix;
			rdn.bv_len -= op->o_req_ndn.bv_len + STRLENOF( "," );
			if ( dnIsOneLevelRDN( &rdn )
					&& dnIsSuffix( &mt->mt_nsuffix, &op->o_req_ndn ) )
			{
				/*
				 * if there is exactly one level,
				 * make the target suffix the new
				 * base, and make scope "base"
				 */
				realbase = mt->mt_nsuffix;
				if ( op->ors_scope == LDAP_SCOPE_SUBORDINATE ) {
					if ( mt->mt_scope == LDAP_SCOPE_SUBORDINATE ) {
						realscope = LDAP_SCOPE_SUBORDINATE;
					} else {
						realscope = LDAP_SCOPE_SUBTREE;
					}
				} else {
					realscope = LDAP_SCOPE_BASE;
				}
				break;
			} /* else continue with the next case */
		}

		case LDAP_SCOPE_BASE:
			/*
			 * this target is no longer candidate
			 */
			retcode = META_SEARCH_NOT_CANDIDATE;
			goto doreturn;
		}
	}

	/* check filter expression */
	if ( mt->mt_filter ) {
		metafilter_t *mf;
		for ( mf = mt->mt_filter; mf; mf = mf->mf_next ) {
			if ( regexec( &mf->mf_regex, op->ors_filterstr.bv_val, 0, NULL, 0 ) == 0 )
				break;
		}
		/* nothing matched, this target is no longer a candidate */
		if ( !mf ) {
			retcode = META_SEARCH_NOT_CANDIDATE;
			goto doreturn;
		}
	}

	/*
	 * Rewrite the search base, if required
	 */
	dc.target = mt;
	dc.ctx = "searchBase";
	dc.conn = op->o_conn;
	dc.rs = rs;
	switch ( asyncmeta_dn_massage( &dc, &realbase, &mbase ) ) {
	case LDAP_SUCCESS:
		break;

	case LDAP_UNWILLING_TO_PERFORM:
		rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
		rs->sr_text = "Operation not allowed";
		retcode = META_SEARCH_ERR;
		goto doreturn;

	default:

		/*
		 * this target is no longer candidate
		 */
		retcode = META_SEARCH_NOT_CANDIDATE;
		goto doreturn;
	}

	/*
	 * Maps filter
	 */
	rc = asyncmeta_filter_map_rewrite( &dc, op->ors_filter,
			&mfilter, BACKLDAP_MAP, NULL );
	switch ( rc ) {
	case LDAP_SUCCESS:
		break;

	case LDAP_COMPARE_FALSE:
	default:
		/*
		 * this target is no longer candidate
		 */
		retcode = META_SEARCH_NOT_CANDIDATE;
		goto done;
	}

	/*
	 * Maps required attributes
	 */
	rc = asyncmeta_map_attrs( op, &mt->mt_rwmap.rwm_at,
			op->ors_attrs, BACKLDAP_MAP, &mapped_attrs );
	if ( rc != LDAP_SUCCESS ) {
		/*
		 * this target is no longer candidate
		 */
		retcode = META_SEARCH_NOT_CANDIDATE;
		goto done;
	}

	if ( op->ors_tlimit != SLAP_NO_LIMIT ) {
		timelimit = op->ors_tlimit > 0 ? op->ors_tlimit : 1;
	} else {
		timelimit = -1;	/* no limit */
	}

#ifdef SLAPD_META_CLIENT_PR
	save_ctrls = op->o_ctrls;
	{
		LDAPControl *pr_c = NULL;
		int i = 0, nc = 0;

		if ( save_ctrls ) {
			for ( ; save_ctrls[i] != NULL; i++ );
			nc = i;
			pr_c = ldap_control_find( LDAP_CONTROL_PAGEDRESULTS, save_ctrls, NULL );
		}

		if ( pr_c != NULL ) nc--;
		if ( mt->mt_ps > 0 || prcookie != NULL ) nc++;

		if ( mt->mt_ps > 0 || prcookie != NULL || pr_c != NULL ) {
			int src = 0, dst = 0;
			BerElementBuffer berbuf;
			BerElement *ber = (BerElement *)&berbuf;
			struct berval val = BER_BVNULL;
			ber_len_t len;

			len = sizeof( LDAPControl * )*( nc + 1 ) + sizeof( LDAPControl );

			if ( mt->mt_ps > 0 || prcookie != NULL ) {
				struct berval nullcookie = BER_BVNULL;
				ber_tag_t tag;

				if ( prsize == 0 && mt->mt_ps > 0 ) prsize = mt->mt_ps;
				if ( prcookie == NULL ) prcookie = &nullcookie;

				ber_init2( ber, NULL, LBER_USE_DER );
				tag = ber_printf( ber, "{iO}", prsize, prcookie );
				if ( tag == LBER_ERROR ) {
					/* error */
					(void) ber_free_buf( ber );
					goto done_pr;
				}

				tag = ber_flatten2( ber, &val, 0 );
				if ( tag == LBER_ERROR ) {
					/* error */
					(void) ber_free_buf( ber );
					goto done_pr;
				}

				len += val.bv_len + 1;
			}

			op->o_ctrls = op->o_tmpalloc( len, op->o_tmpmemctx );
			if ( save_ctrls ) {
				for ( ; save_ctrls[ src ] != NULL; src++ ) {
					if ( save_ctrls[ src ] != pr_c ) {
						op->o_ctrls[ dst ] = save_ctrls[ src ];
						dst++;
					}
				}
			}

			if ( mt->mt_ps > 0 || prcookie != NULL ) {
				op->o_ctrls[ dst ] = (LDAPControl *)&op->o_ctrls[ nc + 1 ];

				op->o_ctrls[ dst ]->ldctl_oid = LDAP_CONTROL_PAGEDRESULTS;
				op->o_ctrls[ dst ]->ldctl_iscritical = 1;

				op->o_ctrls[ dst ]->ldctl_value.bv_val = (char *)&op->o_ctrls[ dst ][ 1 ];
				AC_MEMCPY( op->o_ctrls[ dst ]->ldctl_value.bv_val, val.bv_val, val.bv_len + 1 );
				op->o_ctrls[ dst ]->ldctl_value.bv_len = val.bv_len;
				dst++;

				(void)ber_free_buf( ber );
			}

			op->o_ctrls[ dst ] = NULL;
		}
done_pr:;
	}
#endif /* SLAPD_META_CLIENT_PR */

retry:;
	asyncmeta_set_msc_time(msc);
	ctrls = op->o_ctrls;
	if (nretries == 0)
	{
		if (rc != LDAP_SUCCESS)
		{
			rs->sr_err = LDAP_BUSY;
			retcode = META_SEARCH_ERR;
			candidates[ candidate ].sr_msgid = META_MSGID_IGNORE;
		        goto done;
		}
	}

	if ( asyncmeta_controls_add( op, rs, mc, candidate, &ctrls )
		!= LDAP_SUCCESS )
	{
		candidates[ candidate ].sr_msgid = META_MSGID_IGNORE;
		retcode = META_SEARCH_NOT_CANDIDATE;
		goto done;
	}

	/*
	 * Starts the search
	 */
	ber = ldap_build_search_req( msc->msc_ld,
			mbase.bv_val, realscope, mfilter.bv_val,
			mapped_attrs, op->ors_attrsonly,
			ctrls, NULL, timelimit, op->ors_slimit, op->ors_deref,
			&msgid );
	if (ber) {
		candidates[ candidate ].sr_msgid = msgid;
		rc = ldap_send_initial_request( msc->msc_ld, LDAP_REQ_SEARCH,
			mbase.bv_val, ber, msgid );
		if (rc == msgid)
			rc = LDAP_SUCCESS;
		else
			rc = LDAP_SERVER_DOWN;
		switch ( rc ) {
		case LDAP_SUCCESS:
			retcode = META_SEARCH_CANDIDATE;
			asyncmeta_set_msc_time(msc);
			break;

		case LDAP_SERVER_DOWN:
			ldap_pvt_thread_mutex_lock( &mc->mc_om_mutex);
			if (mc->mc_active < 1) {
				asyncmeta_clear_one_msc(NULL, mc, candidate);
			}
			ldap_pvt_thread_mutex_unlock( &mc->mc_om_mutex);
			if ( nretries && asyncmeta_retry( op, rs, &mc, candidate, LDAP_BACK_DONTSEND ) ) {
				nretries = 0;
				/* if the identity changed, there might be need to re-authz */
				(void)mi->mi_ldap_extra->controls_free( op, rs, &ctrls );
				goto retry;
			}
			rs->sr_err = LDAP_UNAVAILABLE;
			retcode = META_SEARCH_ERR;
			break;
		default:
			candidates[ candidate ].sr_msgid = META_MSGID_IGNORE;
			retcode = META_SEARCH_NOT_CANDIDATE;
		}
	}

done:;
	(void)mi->mi_ldap_extra->controls_free( op, rs, &ctrls );
#ifdef SLAPD_META_CLIENT_PR
	if ( save_ctrls != op->o_ctrls ) {
		op->o_tmpfree( op->o_ctrls, op->o_tmpmemctx );
		op->o_ctrls = save_ctrls;
	}
#endif /* SLAPD_META_CLIENT_PR */

	if ( mapped_attrs ) {
		ber_memfree_x( mapped_attrs, op->o_tmpmemctx );
	}
	if ( mfilter.bv_val != op->ors_filterstr.bv_val ) {
		ber_memfree_x( mfilter.bv_val, NULL );
	}
	if ( mbase.bv_val != realbase.bv_val ) {
		free( mbase.bv_val );
	}

doreturn:;
	Debug( LDAP_DEBUG_TRACE, "%s <<< asyncmeta_back_search_start[%p]=%d\n", op->o_log_prefix, msc, candidates[candidate].sr_msgid );
	return retcode;
}