Example #1
0
static int
valsort_parseCtrl(
	Operation *op,
	SlapReply *rs,
	LDAPControl *ctrl )
{
	ber_tag_t tag;
	BerElementBuffer berbuf;
	BerElement *ber = (BerElement *)&berbuf;
	ber_int_t flag = 0;

	if ( BER_BVISNULL( &ctrl->ldctl_value )) {
		rs->sr_text = "valSort control value is absent";
		return LDAP_PROTOCOL_ERROR;
	}

	if ( BER_BVISEMPTY( &ctrl->ldctl_value )) {
		rs->sr_text = "valSort control value is empty";
		return LDAP_PROTOCOL_ERROR;
	}

	ber_init2( ber, &ctrl->ldctl_value, 0 );
	if (( tag = ber_scanf( ber, "{b}", &flag )) == LBER_ERROR ) {
		rs->sr_text = "valSort control: flag decoding error";
		return LDAP_PROTOCOL_ERROR;
	}

	op->o_ctrlflag[valsort_cid] = ctrl->ldctl_iscritical ?
		SLAP_CONTROL_CRITICAL : SLAP_CONTROL_NONCRITICAL;
	if ( flag )
		op->o_ctrlflag[valsort_cid] |= SLAP_CONTROL_DATA0;

	return LDAP_SUCCESS;
}
Example #2
0
File: tls_g.c Project: 1ack/Impala
static void
tlsg_x509_cert_dn( struct berval *cert, struct berval *dn, int get_subject )
{
	BerElementBuffer berbuf;
	BerElement *ber = (BerElement *)&berbuf;
	ber_tag_t tag;
	ber_len_t len;
	ber_int_t i;

	ber_init2( ber, cert, LBER_USE_DER );
	tag = ber_skip_tag( ber, &len );	/* Sequence */
	tag = ber_skip_tag( ber, &len );	/* Sequence */
	tag = ber_skip_tag( ber, &len );	/* Context + Constructed (version) */
	if ( tag == 0xa0 )	/* Version is optional */
		tag = ber_get_int( ber, &i );	/* Int: Version */
	tag = ber_skip_tag( ber, &len );	/* Int: Serial (can be longer than ber_int_t) */
	ber_skip_data( ber, len );
	tag = ber_skip_tag( ber, &len );	/* Sequence: Signature */
	ber_skip_data( ber, len );
	if ( !get_subject ) {
		tag = ber_peek_tag( ber, &len );	/* Sequence: Issuer DN */
	} else {
		tag = ber_skip_tag( ber, &len );
		ber_skip_data( ber, len );
		tag = ber_skip_tag( ber, &len );	/* Sequence: Validity */
		ber_skip_data( ber, len );
		tag = ber_peek_tag( ber, &len );	/* Sequence: Subject DN */
	}
	len = ber_ptrlen( ber );
	dn->bv_val = cert->bv_val + len;
	dn->bv_len = cert->bv_len - len;
}
Example #3
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;
}
Example #4
0
int
ParseSyncStateControlVal(
    BerValue *  controlValue,   // Input: control value encoded as ber,
    int *       entryState)     // Output
{
    int                 retVal = LDAP_SUCCESS;
    BerElementBuffer    berbuf;
    BerElement *        ber = (BerElement *)&berbuf;

    VMDIR_LOG_DEBUG( LDAP_DEBUG_TRACE, "ParseSyncStateControlVal: Begin." );

    ber_init2( ber, controlValue, LBER_USE_DER );

    if (ber_scanf( ber, "{i}", entryState ) == -1 )
    {
        VMDIR_LOG_ERROR(VMDIR_LOG_MASK_ALL, "ParseSyncStateControlVal: ber_scanf to read entryState failed" );
        retVal = LDAP_OPERATIONS_ERROR;
        BAIL_ON_VMDIR_ERROR( retVal );
    }

cleanup:
    VMDIR_LOG_DEBUG( LDAP_DEBUG_TRACE, "ParseSyncStateControlVal: Begin." );
    return retVal;

error:
    goto cleanup;
}
Example #5
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 );

	ber_init2( ber, NULL, 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;
}
Example #6
0
static
int
_ParseCondWriteControlVal(
    VDIR_OPERATION *                        pOp,
    BerValue *                              pControlBer,    // Input: control value encoded as ber
    VDIR_CONDWRITE_CONTROL_VALUE *          pCtrlVal,       // Output
    VDIR_LDAP_RESULT *                      pLdapResult     // Output
    )
{
    int                 retVal = LDAP_SUCCESS;
    BerElementBuffer    berbuf;
    BerElement *        ber = (BerElement *)&berbuf;
    PSTR                pszLocalErrorMsg = NULL;
    PSTR                pszCondFilter = NULL;

    if (!pOp)
    {
        retVal = LDAP_PROTOCOL_ERROR;
        BAIL_ON_VMDIR_ERROR( retVal );
    }

    ber_init2( ber, pControlBer, LBER_USE_DER );

    /*
     * https://confluence.eng.vmware.com/display/LIG/Conditional+LDAP+Write+Operation
     *
     * The ConditionalWriteControl is a null terminated STRING wrapping the BER-encoded version of the following SEQUENCE:
     *
     * ControlValue ::= SEQUENCE {
     *        ConditionalWriteFilter            OCTET STRING
     *  }
     */

    if (ber_scanf(ber, "{a}", &pszCondFilter) == LBER_ERROR)
    {
        VMDIR_LOG_ERROR( VMDIR_LOG_MASK_ALL, "%s: ber_scanf failed while parsing filter value", __FUNCTION__);
        pLdapResult->errCode = LDAP_PROTOCOL_ERROR;
        retVal = LDAP_NOTICE_OF_DISCONNECT;
        BAIL_ON_VMDIR_ERROR_WITH_MSG(   retVal, (pszLocalErrorMsg),
                                        "Error in reading conditional write control filter");
    }

    retVal = VmDirAllocateStringA(pszCondFilter, &(pCtrlVal->pszFilter));
    BAIL_ON_VMDIR_ERROR(retVal);

cleanup:
    if (pszCondFilter)
    {
        ber_memfree(pszCondFilter);
    }
    VMDIR_SAFE_FREE_MEMORY(pszLocalErrorMsg);

    return retVal;

error:
    VMDIR_APPEND_ERROR_MSG(pLdapResult->pszErrMsg, pszLocalErrorMsg);
    goto cleanup;
}
Example #7
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;
}
Example #8
0
int slap_read_controls(
	Operation *op,
	SlapReply *rs,
	Entry *e,
	const struct berval *oid,
	LDAPControl **ctrl )
{
	int rc;
	struct berval bv;
	BerElementBuffer berbuf;
	BerElement *ber = (BerElement *) &berbuf;
	LDAPControl c;
	Operation myop;

	Debug( LDAP_DEBUG_ANY, "%s slap_read_controls: (%s) %s\n",
		op->o_log_prefix, oid->bv_val, e->e_dn );

	rs->sr_entry = e;
	rs->sr_attrs = ( oid == &slap_pre_read_bv ) ?
		op->o_preread_attrs : op->o_postread_attrs;

	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 );

	/* create new operation */
	myop = *op;
	/* FIXME: o_bd needed for ACL */
	myop.o_bd = op->o_bd;
	myop.o_res_ber = ber;
	myop.o_callback = NULL;
	myop.ors_slimit = 1;
	myop.ors_attrsonly = 0;

	rc = slap_send_search_entry( &myop, rs );
	if( rc ) return rc;

	rc = ber_flatten2( ber, &c.ldctl_value, 0 );

	if( rc == -1 ) return LDAP_OTHER;

	c.ldctl_oid = oid->bv_val;
	c.ldctl_iscritical = 0;

	if ( *ctrl == NULL ) {
		/* first try */
		*ctrl = (LDAPControl *) slap_sl_calloc( 1, sizeof(LDAPControl), NULL );
	} else {
		/* retry: free previous try */
		slap_sl_free( (*ctrl)->ldctl_value.bv_val, op->o_tmpmemctx );
	}

	**ctrl = c;
	return LDAP_SUCCESS;
}
Example #9
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;
}
Example #10
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 );
}
Example #11
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;
}
Example #12
0
/* Rewrite an LDAP DN in DER form
 * Input must be valid DN, therefore no error checking is done here.
 */
static int autoca_dnbv2der( Operation *op, struct berval *bv, struct berval *der )
{
	BerElementBuffer berbuf;
	BerElement *ber = (BerElement *)&berbuf;
	LDAPDN dn;
	LDAPRDN rdn;
	LDAPAVA *ava;
	AttributeDescription *ad;
	int irdn, iava;

	ldap_bv2dn_x( bv, &dn, LDAP_DN_FORMAT_LDAP, op->o_tmpmemctx );

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

	/* count RDNs, we need them in reverse order */
	for (irdn = 0; dn[irdn]; irdn++);
	irdn--;

	/* DN is a SEQuence of RDNs */
	ber_start_seq( ber, LBER_SEQUENCE );
	for (; irdn >=0; irdn--)
	{
		/* RDN is a SET of AVAs */
		ber_start_set( ber, LBER_SET );
		rdn = dn[irdn];
		for (iava = 0; rdn[iava]; iava++)
		{
			const char *text;
			char oid[1024];
			struct berval bvo = { sizeof(oid), oid };
			struct berval bva;

			/* AVA is a SEQuence of attr and value */
			ber_start_seq( ber, LBER_SEQUENCE );
			ava = rdn[iava];
			ad = NULL;
			slap_bv2ad( &ava->la_attr, &ad, &text );
			ber_str2bv( ad->ad_type->sat_oid, 0, 0, &bva );
			ber_encode_oid( &bva, &bvo );
			ber_put_berval( ber, &bvo, LBER_TAG_OID );
			ber_put_berval( ber, &ava->la_value, LBER_TAG_UTF8 );
			ber_put_seq( ber );
		}
		ber_put_set( ber );
	}
	ber_put_seq( ber );
	ber_flatten2( ber, der, 0 );
	ldap_dnfree_x( dn, op->o_tmpmemctx );
	return 0;
}
Example #13
0
/* Conforms to RFC4510 re: Criticality, original RFC2891 spec is broken
 * Also see ITS#7253 for discussion
 */
static int sss_parseCtrl(
	Operation		*op,
	SlapReply		*rs,
	LDAPControl		*ctrl )
{
	BerElementBuffer	berbuf;
	BerElement			*ber;
	ber_tag_t		tag;
	ber_len_t		len;
	int					i;
	sort_ctrl	*sc;

	rs->sr_err = LDAP_PROTOCOL_ERROR;

	if ( op->o_ctrlflag[sss_cid] > SLAP_CONTROL_IGNORED ) {
		rs->sr_text = "sorted results control specified multiple times";
	} else if ( BER_BVISNULL( &ctrl->ldctl_value ) ) {
		rs->sr_text = "sorted results control value is absent";
	} else if ( BER_BVISEMPTY( &ctrl->ldctl_value ) ) {
		rs->sr_text = "sorted results control value is empty";
	} else {
		rs->sr_err = LDAP_SUCCESS;
	}
	if ( rs->sr_err != LDAP_SUCCESS )
		return rs->sr_err;

	op->o_ctrlflag[sss_cid] = ctrl->ldctl_iscritical ?
		SLAP_CONTROL_CRITICAL : SLAP_CONTROL_NONCRITICAL;

	ber = (BerElement *)&berbuf;
	ber_init2( ber, &ctrl->ldctl_value, 0 );
	i = count_key( ber );

	sc = op->o_tmpalloc( sizeof(sort_ctrl) +
		(i-1) * sizeof(sort_key), op->o_tmpmemctx );
	sc->sc_nkeys = i;
	op->o_controls[sss_cid] = sc;

	/* peel off initial sequence */
	ber_scanf( ber, "{" );

	i = 0;
	do {
		if ( build_key( ber, rs, &sc->sc_keys[i] ) != LDAP_SUCCESS )
			break;
		i++;
		tag = ber_peek_tag( ber, &len );
	} while ( tag != LBER_DEFAULT );

	return rs->sr_err;
}
Example #14
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;
}
Example #15
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;
}
Example #16
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;
}
Example #17
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;
}
Example #18
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;
}
Example #19
0
/* NOTE: The DN in *id is NOT NUL-terminated here. dnNormalize will
 * reject it in this condition, the caller must NUL-terminate it.
 * FIXME: should dnNormalize still be complaining about that?
 */
int slap_passwd_parse( struct berval *reqdata,
	struct berval *id,
	struct berval *oldpass,
	struct berval *newpass,
	const char **text )
{
	int rc = LDAP_SUCCESS;
	ber_tag_t tag;
	ber_len_t len = -1;
	BerElementBuffer berbuf;
	BerElement *ber = (BerElement *)&berbuf;

	if( reqdata == NULL ) {
		return LDAP_SUCCESS;
	}

	if( reqdata->bv_len == 0 ) {
		*text = "empty request data field";
		return LDAP_PROTOCOL_ERROR;
	}

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

	tag = ber_skip_tag( ber, &len );

	if( tag != LBER_SEQUENCE ) {
		Debug( LDAP_DEBUG_TRACE,
			"slap_passwd_parse: decoding error\n", 0, 0, 0 );
		rc = LDAP_PROTOCOL_ERROR;
		goto done;
	}

	tag = ber_peek_tag( ber, &len );
	if( tag == LDAP_TAG_EXOP_MODIFY_PASSWD_ID ) {
		if( id == NULL ) {
			Debug( LDAP_DEBUG_TRACE, "slap_passwd_parse: ID not allowed.\n",
				0, 0, 0 );

			*text = "user must change own password";
			rc = LDAP_UNWILLING_TO_PERFORM;
			goto done;
		}

		tag = ber_get_stringbv( ber, id, LBER_BV_NOTERM );

		if( tag == LBER_ERROR ) {
			Debug( LDAP_DEBUG_TRACE, "slap_passwd_parse: ID parse failed.\n",
				0, 0, 0 );

			goto decoding_error;
		}

		tag = ber_peek_tag( ber, &len );
	}

	if( tag == LDAP_TAG_EXOP_MODIFY_PASSWD_OLD ) {
		if( oldpass == NULL ) {
			Debug( LDAP_DEBUG_TRACE, "slap_passwd_parse: OLD not allowed.\n",
				0, 0, 0 );

			*text = "use bind to verify old password";
			rc = LDAP_UNWILLING_TO_PERFORM;
			goto done;
		}

		tag = ber_get_stringbv( ber, oldpass, LBER_BV_NOTERM );

		if( tag == LBER_ERROR ) {
			Debug( LDAP_DEBUG_TRACE, "slap_passwd_parse: OLD parse failed.\n",
				0, 0, 0 );

			goto decoding_error;
		}

		if( oldpass->bv_len == 0 ) {
			Debug( LDAP_DEBUG_TRACE, "slap_passwd_parse: OLD empty.\n",
				0, 0, 0 );

			*text = "old password value is empty";
			rc = LDAP_UNWILLING_TO_PERFORM;
			goto done;
		}

		tag = ber_peek_tag( ber, &len );
	}

	if( tag == LDAP_TAG_EXOP_MODIFY_PASSWD_NEW ) {
		if( newpass == NULL ) {
			Debug( LDAP_DEBUG_TRACE, "slap_passwd_parse: NEW not allowed.\n",
				0, 0, 0 );

			*text = "user specified passwords disallowed";
			rc = LDAP_UNWILLING_TO_PERFORM;
			goto done;
		}

		tag = ber_get_stringbv( ber, newpass, LBER_BV_NOTERM );

		if( tag == LBER_ERROR ) {
			Debug( LDAP_DEBUG_TRACE, "slap_passwd_parse: NEW parse failed.\n",
				0, 0, 0 );

			goto decoding_error;
		}

		if( newpass->bv_len == 0 ) {
			Debug( LDAP_DEBUG_TRACE, "slap_passwd_parse: NEW empty.\n",
				0, 0, 0 );

			*text = "new password value is empty";
			rc = LDAP_UNWILLING_TO_PERFORM;
			goto done;
		}

		tag = ber_peek_tag( ber, &len );
	}

	if( len != 0 ) {
decoding_error:
		Debug( LDAP_DEBUG_TRACE,
			"slap_passwd_parse: decoding error, len=%ld\n",
			(long) len, 0, 0 );

		*text = "data decoding error";
		rc = LDAP_PROTOCOL_ERROR;
	}

done:
	return rc;
}
Example #20
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;
}
Example #21
0
static int
deref_parseCtrl (
	Operation *op,
	SlapReply *rs,
	LDAPControl *ctrl )
{
	ber_tag_t tag;
	BerElementBuffer berbuf;
	BerElement *ber = (BerElement *)&berbuf;
	ber_len_t len;
	char *last;
	DerefSpec *dshead = NULL, **dsp = &dshead;
	BerVarray attributes = NULL;

	if ( op->o_deref != SLAP_CONTROL_NONE ) {
		rs->sr_text = "Dereference control specified multiple times";
		return LDAP_PROTOCOL_ERROR;
	}

	if ( BER_BVISNULL( &ctrl->ldctl_value ) ) {
		rs->sr_text = "Dereference control value is absent";
		return LDAP_PROTOCOL_ERROR;
	}

	if ( BER_BVISEMPTY( &ctrl->ldctl_value ) ) {
		rs->sr_text = "Dereference control value is empty";
		return LDAP_PROTOCOL_ERROR;
	}

	ber_init2( ber, &ctrl->ldctl_value, 0 );

	for ( tag = ber_first_element( ber, &len, &last );
		tag != LBER_DEFAULT;
		tag = ber_next_element( ber, &len, last ) )
	{
		struct berval derefAttr;
		DerefSpec *ds, *dstmp;
		const char *text;
		int rc;
		ber_len_t cnt = sizeof(struct berval);
		ber_len_t off = 0;

		if ( ber_scanf( ber, "{m{M}}", &derefAttr, &attributes, &cnt, off ) == LBER_ERROR
			|| !cnt )
		{
			rs->sr_text = "Dereference control: derefSpec decoding error";
			rs->sr_err = LDAP_PROTOCOL_ERROR;
			goto done;
		}

		ds = (DerefSpec *)op->o_tmpcalloc( 1,
			sizeof(DerefSpec) + sizeof(AttributeDescription *)*(cnt + 1),
			op->o_tmpmemctx );
		ds->ds_attributes = (AttributeDescription **)&ds[ 1 ];
		ds->ds_nattrs = cnt;

		rc = slap_bv2ad( &derefAttr, &ds->ds_derefAttr, &text );
		if ( rc != LDAP_SUCCESS ) {
			rs->sr_text = "Dereference control: derefAttr decoding error";
			rs->sr_err = LDAP_PROTOCOL_ERROR;
			goto done;
		}

		for ( dstmp = dshead; dstmp && dstmp != ds; dstmp = dstmp->ds_next ) {
			if ( dstmp->ds_derefAttr == ds->ds_derefAttr ) {
				rs->sr_text = "Dereference control: derefAttr must be unique within control";
				rs->sr_err = LDAP_PROTOCOL_ERROR;
				goto done;
			}
		}

		if ( !( ds->ds_derefAttr->ad_type->sat_syntax->ssyn_flags & SLAP_SYNTAX_DN )) {
			if ( ctrl->ldctl_iscritical ) {
				rs->sr_text = "Dereference control: derefAttr syntax not distinguishedName";
				rs->sr_err = LDAP_PROTOCOL_ERROR;
				goto done;
			}

			rs->sr_err = LDAP_SUCCESS;
			goto justcleanup;
		}

		for ( cnt = 0; !BER_BVISNULL( &attributes[ cnt ] ); cnt++ ) {
			rc = slap_bv2ad( &attributes[ cnt ], &ds->ds_attributes[ cnt ], &text );
			if ( rc != LDAP_SUCCESS ) {
				rs->sr_text = "Dereference control: attribute decoding error";
				rs->sr_err = LDAP_PROTOCOL_ERROR;
				goto done;
			}
		}

		ber_memfree_x( attributes, op->o_tmpmemctx );
		attributes = NULL;

		*dsp = ds;
		dsp = &ds->ds_next;
	}

	op->o_ctrlderef = (void *)dshead;

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

	rs->sr_err = LDAP_SUCCESS;

done:;
	if ( rs->sr_err != LDAP_SUCCESS ) {
justcleanup:;
		for ( ; dshead; ) {
			DerefSpec *dsnext = dshead->ds_next;
			op->o_tmpfree( dshead, op->o_tmpmemctx );
			dshead = dsnext;
		}
	}

	if ( attributes != NULL ) {
		ber_memfree_x( attributes, op->o_tmpmemctx );
	}

	return rs->sr_err;
}
Example #22
0
static int
ldap_back_exop_passwd(
	Operation	*op,
	SlapReply	*rs,
	ldapconn_t	**lcp )
{
	ldapinfo_t	*li = (ldapinfo_t *) op->o_bd->be_private;

	ldapconn_t	*lc = *lcp;
	req_pwdexop_s	*qpw = &op->oq_pwdexop;
	LDAPMessage	*res;
	ber_int_t	msgid;
	int		rc, isproxy, freedn = 0;
	int		do_retry = 1;
	char		*text = NULL;
	struct berval	dn = op->o_req_dn,
			ndn = op->o_req_ndn;

	assert( lc != NULL );
	assert( rs->sr_ctrls == NULL );

	if ( BER_BVISNULL( &ndn ) && op->ore_reqdata != NULL ) {
		/* NOTE: most of this code is mutated
		 * from slap_passwd_parse();
		 * But here we only need
		 * the first berval... */

		ber_tag_t tag;
		ber_len_t len = -1;
		BerElementBuffer berbuf;
		BerElement *ber = (BerElement *)&berbuf;

		struct berval	tmpid = BER_BVNULL;

		if ( op->ore_reqdata->bv_len == 0 ) {
			return LDAP_PROTOCOL_ERROR;
		}

		/* ber_init2 uses reqdata directly, doesn't allocate new buffers */
		ber_init2( ber, op->ore_reqdata, 0 );

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

		if ( tag == LBER_ERROR ) {
			return LDAP_PROTOCOL_ERROR;
		}

		tag = ber_peek_tag( ber, &len );
		if ( tag == LDAP_TAG_EXOP_MODIFY_PASSWD_ID ) {
			tag = ber_get_stringbv( ber, &tmpid, LBER_BV_NOTERM );

			if ( tag == LBER_ERROR ) {
				return LDAP_PROTOCOL_ERROR;
			}
		}

		if ( !BER_BVISEMPTY( &tmpid ) ) {
			char idNull = tmpid.bv_val[tmpid.bv_len];
			tmpid.bv_val[tmpid.bv_len] = '\0';
			rs->sr_err = dnPrettyNormal( NULL, &tmpid, &dn,
				&ndn, op->o_tmpmemctx );
			tmpid.bv_val[tmpid.bv_len] = idNull;
			if ( rs->sr_err != LDAP_SUCCESS ) {
				/* should have been successfully parsed earlier! */
				return rs->sr_err;
			}
			freedn = 1;

		} else {
			dn = op->o_dn;
			ndn = op->o_ndn;
		}
	}

	isproxy = ber_bvcmp( &ndn, &op->o_ndn );

	Debug( LDAP_DEBUG_ARGS, "==> ldap_back_exop_passwd(\"%s\")%s\n",
		dn.bv_val, isproxy ? " (proxy)" : "", 0 );

retry:
	rc = ldap_passwd( lc->lc_ld,  &dn,
		qpw->rs_old.bv_val ? &qpw->rs_old : NULL,
		qpw->rs_new.bv_val ? &qpw->rs_new : NULL,
		op->o_ctrls, NULL, &msgid );

	if ( rc == LDAP_SUCCESS ) {
		/* TODO: set timeout? */
		/* by now, make sure no timeout is used (ITS#6282) */
		struct timeval tv = { -1, 0 };
		if ( ldap_result( lc->lc_ld, msgid, LDAP_MSG_ALL, &tv, &res ) == -1 ) {
			ldap_get_option( lc->lc_ld, LDAP_OPT_ERROR_NUMBER, &rc );
			rs->sr_err = rc;

		} else {
			/* only touch when activity actually took place... */
			if ( li->li_idle_timeout ) {
				lc->lc_time = op->o_time;
			}

			/* sigh. parse twice, because parse_passwd
			 * doesn't give us the err / match / msg info.
			 */
			rc = ldap_parse_result( lc->lc_ld, res, &rs->sr_err,
					(char **)&rs->sr_matched,
					&text,
					NULL, &rs->sr_ctrls, 0 );

			if ( rc == LDAP_SUCCESS ) {
				if ( rs->sr_err == LDAP_SUCCESS ) {
					struct berval	newpw;

					/* this never happens because 
					 * the frontend	is generating 
					 * the new password, so when
					 * the passwd exop is proxied,
					 * it never delegates password
					 * generation to the remote server
					 */
					rc = ldap_parse_passwd( lc->lc_ld, res,
							&newpw );
					if ( rc == LDAP_SUCCESS &&
							!BER_BVISNULL( &newpw ) )
					{
						rs->sr_type = REP_EXTENDED;
						rs->sr_rspdata = slap_passwd_return( &newpw );
						free( newpw.bv_val );
					}

				} else {
					rc = rs->sr_err;
				}
			}
			ldap_msgfree( res );
		}
	}

	if ( rc != LDAP_SUCCESS ) {
		rs->sr_err = slap_map_api2result( rs );
		if ( rs->sr_err == LDAP_UNAVAILABLE && do_retry ) {
			do_retry = 0;
			if ( ldap_back_retry( &lc, op, rs, LDAP_BACK_SENDERR ) ) {
				goto retry;
			}
		}

		if ( LDAP_BACK_QUARANTINE( li ) ) {
			ldap_back_quarantine( op, rs );
		}

		if ( text ) rs->sr_text = text;
		send_ldap_extended( op, rs );
		/* otherwise frontend resends result */
		rc = rs->sr_err = SLAPD_ABANDON;

	} else if ( LDAP_BACK_QUARANTINE( li ) ) {
		ldap_back_quarantine( op, rs );
	}

	ldap_pvt_thread_mutex_lock( &li->li_counter_mutex );
	ldap_pvt_mp_add( li->li_ops_completed[ SLAP_OP_EXTENDED ], 1 );
	ldap_pvt_thread_mutex_unlock( &li->li_counter_mutex );

	if ( freedn ) {
		op->o_tmpfree( dn.bv_val, op->o_tmpmemctx );
		op->o_tmpfree( ndn.bv_val, op->o_tmpmemctx );
	}

	/* these have to be freed anyway... */
	if ( rs->sr_matched ) {
		free( (char *)rs->sr_matched );
		rs->sr_matched = NULL;
	}

	if ( rs->sr_ctrls ) {
		ldap_controls_free( rs->sr_ctrls );
		rs->sr_ctrls = NULL;
	}

	if ( text ) {
		free( text );
		rs->sr_text = NULL;
	}

	/* in case, cleanup handler */
	if ( lc == NULL ) {
		*lcp = NULL;
	}

	return rc;
}
Example #23
0
int
asyncmeta_handle_search_msg(LDAPMessage *res, a_metaconn_t *mc, bm_context_t *bc, int candidate)
{
	a_metainfo_t	*mi;
	a_metatarget_t	*mt;
	a_metasingleconn_t *msc;
	Operation *op = bc->op;
	SlapReply *rs;
	int	   i, rc = LDAP_SUCCESS, sres;
	SlapReply *candidates;
	char		**references = NULL;
	LDAPControl	**ctrls = NULL;
	a_dncookie dc;
	LDAPMessage *msg;
	ber_int_t id;

	rs = &bc->rs;
	mi = mc->mc_info;
	mt = mi->mi_targets[ candidate ];
	msc = &mc->mc_conns[ candidate ];
	dc.op = op;
	dc.target = mt;
	dc.to_from = MASSAGE_REP;
	id = ldap_msgid(res);


	candidates = bc->candidates;
	i = candidate;

	while (res && !META_BACK_CONN_INVALID(msc)) {
	for (msg = ldap_first_message(msc->msc_ldr, res); msg; msg = ldap_next_message(msc->msc_ldr, msg)) {
		switch(ldap_msgtype(msg)) {
		case LDAP_RES_SEARCH_ENTRY:
			Debug( LDAP_DEBUG_TRACE,
				"%s asyncmeta_handle_search_msg: msc %p entry\n",
				op->o_log_prefix, msc );
			if ( candidates[ i ].sr_type == REP_INTERMEDIATE ) {
				/* don't retry any more... */
				candidates[ i ].sr_type = REP_RESULT;
			}
			/* count entries returned by target */
			candidates[ i ].sr_nentries++;
			if (bc->c_peer_name.bv_val == op->o_conn->c_peer_name.bv_val && !op->o_abandon) {
				rs->sr_err = asyncmeta_send_entry( &bc->copy_op, rs, mc, i, msg );
			} else {
				goto err_cleanup;
			}
			switch ( rs->sr_err ) {
			case LDAP_SIZELIMIT_EXCEEDED:
				asyncmeta_send_ldap_result(bc, op, rs);
				rs->sr_err = LDAP_SUCCESS;
				goto err_cleanup;
			case LDAP_UNAVAILABLE:
				rs->sr_err = LDAP_OTHER;
				break;
			default:
				break;
			}
			bc->is_ok++;
			break;

		case LDAP_RES_SEARCH_REFERENCE:
			if ( META_BACK_TGT_NOREFS( mt ) ) {
				rs->sr_err = LDAP_OTHER;
				asyncmeta_send_ldap_result(bc, op, rs);
				goto err_cleanup;
			}
			if ( candidates[ i ].sr_type == REP_INTERMEDIATE ) {
				/* don't retry any more... */
				candidates[ i ].sr_type = REP_RESULT;
			}
			bc->is_ok++;
			rc = ldap_parse_reference( msc->msc_ldr, msg,
				   &references, &rs->sr_ctrls, 0 );

			if ( rc != LDAP_SUCCESS || references == NULL ) {
				rs->sr_err = LDAP_OTHER;
				asyncmeta_send_ldap_result(bc, op, rs);
				goto err_cleanup;
			}

			/* FIXME: merge all and return at the end */

			{
				int cnt;
				for ( cnt = 0; references[ cnt ]; cnt++ )
					;

				rs->sr_ref = ber_memalloc_x( sizeof( struct berval ) * ( cnt + 1 ),
								 op->o_tmpmemctx );

				for ( cnt = 0; references[ cnt ]; cnt++ ) {
					ber_str2bv_x( references[ cnt ], 0, 1, &rs->sr_ref[ cnt ],
							  op->o_tmpmemctx );
				}
				BER_BVZERO( &rs->sr_ref[ cnt ] );
			}

			{
				dc.memctx = op->o_tmpmemctx;
				( void )asyncmeta_referral_result_rewrite( &dc, rs->sr_ref );
			}

			if ( rs->sr_ref != NULL ) {
				if (!BER_BVISNULL( &rs->sr_ref[ 0 ] ) ) {
					/* ignore return value by now */
					( void )send_search_reference( op, rs );
				}

				ber_bvarray_free_x( rs->sr_ref, op->o_tmpmemctx );
				rs->sr_ref = NULL;
			}

			/* cleanup */
			if ( references ) {
				ber_memvfree( (void **)references );
			}

			if ( rs->sr_ctrls ) {
				ldap_controls_free( rs->sr_ctrls );
				rs->sr_ctrls = NULL;
			}
			break;

		case LDAP_RES_INTERMEDIATE:
			if ( candidates[ i ].sr_type == REP_INTERMEDIATE ) {
				/* don't retry any more... */
				candidates[ i ].sr_type = REP_RESULT;
			}
			bc->is_ok++;

			/* FIXME: response controls
			 * are passed without checks */
			rs->sr_err = ldap_parse_intermediate( msc->msc_ldr,
								  msg,
								  (char **)&rs->sr_rspoid,
								  &rs->sr_rspdata,
								  &rs->sr_ctrls,
								  0 );
			if ( rs->sr_err != LDAP_SUCCESS ) {
				candidates[ i ].sr_type = REP_RESULT;
				rs->sr_err = LDAP_OTHER;
				asyncmeta_send_ldap_result(bc, op, rs);
				goto err_cleanup;
			}

			slap_send_ldap_intermediate( op, rs );

			if ( rs->sr_rspoid != NULL ) {
				ber_memfree( (char *)rs->sr_rspoid );
				rs->sr_rspoid = NULL;
			}

			if ( rs->sr_rspdata != NULL ) {
				ber_bvfree( rs->sr_rspdata );
				rs->sr_rspdata = NULL;
			}

			if ( rs->sr_ctrls != NULL ) {
				ldap_controls_free( rs->sr_ctrls );
				rs->sr_ctrls = NULL;
			}
			break;

		case LDAP_RES_SEARCH_RESULT:
			if ( mi->mi_idle_timeout != 0 ) {
				asyncmeta_set_msc_time(msc);
			}
			Debug( LDAP_DEBUG_TRACE,
			       "%s asyncmeta_handle_search_msg: msc %p result\n",
			       op->o_log_prefix, msc );
			candidates[ i ].sr_type = REP_RESULT;
			candidates[ i ].sr_msgid = META_MSGID_IGNORE;
			/* NOTE: ignores response controls
			 * (and intermediate response controls
			 * as well, except for those with search
			 * references); this may not be correct,
			 * but if they're not ignored then
			 * back-meta would need to merge them
			 * consistently (think of pagedResults...)
			 */
			/* FIXME: response controls? */
			rs->sr_err = ldap_parse_result( msc->msc_ldr,
							msg,
							&candidates[ i ].sr_err,
								(char **)&candidates[ i ].sr_matched,
							(char **)&candidates[ i ].sr_text,
							&references,
							&ctrls /* &candidates[ i ].sr_ctrls (unused) */ ,
							0 );
			if ( rs->sr_err != LDAP_SUCCESS ) {
				candidates[ i ].sr_err = rs->sr_err;
				sres = slap_map_api2result( &candidates[ i ] );
				candidates[ i ].sr_type = REP_RESULT;
				goto finish;
			}

			rs->sr_err = candidates[ i ].sr_err;

			/* massage matchedDN if need be */
			if ( candidates[ i ].sr_matched != NULL ) {
				struct berval	match, mmatch;

				ber_str2bv( candidates[ i ].sr_matched,
						0, 0, &match );
				candidates[ i ].sr_matched = NULL;

				dc.memctx = NULL;
				asyncmeta_dn_massage( &dc, &match, &mmatch );
				if ( mmatch.bv_val == match.bv_val ) {
					candidates[ i ].sr_matched
						= ch_strdup( mmatch.bv_val );

				} else {
					candidates[ i ].sr_matched = mmatch.bv_val;
				}

				bc->candidate_match++;
				ldap_memfree( match.bv_val );
			}

			/* add references to array */
			/* RFC 4511: referrals can only appear
			 * if result code is LDAP_REFERRAL */
			if ( references != NULL
				 && references[ 0 ] != NULL
				 && references[ 0 ][ 0 ] != '\0' )
			{
				if ( rs->sr_err != LDAP_REFERRAL ) {
					Debug( LDAP_DEBUG_ANY,
						   "%s asncmeta_search_result[%d]: "
						   "got referrals with err=%d\n",
						   op->o_log_prefix,
						   i, rs->sr_err );

				} else {
					BerVarray	sr_ref;
					int		cnt;

					for ( cnt = 0; references[ cnt ]; cnt++ )
						;

					sr_ref = ber_memalloc_x( sizeof( struct berval ) * ( cnt + 1 ),
								 op->o_tmpmemctx );

					for ( cnt = 0; references[ cnt ]; cnt++ ) {
						ber_str2bv_x( references[ cnt ], 0, 1, &sr_ref[ cnt ],
								  op->o_tmpmemctx );
					}
					BER_BVZERO( &sr_ref[ cnt ] );

					dc.memctx = op->o_tmpmemctx;
					( void )asyncmeta_referral_result_rewrite( &dc, sr_ref );

					if ( rs->sr_v2ref == NULL ) {
						rs->sr_v2ref = sr_ref;

					} else {
						for ( cnt = 0; !BER_BVISNULL( &sr_ref[ cnt ] ); cnt++ ) {
							ber_bvarray_add_x( &rs->sr_v2ref, &sr_ref[ cnt ],
									   op->o_tmpmemctx );
						}
						ber_memfree_x( sr_ref, op->o_tmpmemctx );
					}
				}

			} else if ( rs->sr_err == LDAP_REFERRAL ) {
				Debug( LDAP_DEBUG_TRACE,
					   "%s asyncmeta_search_result[%d]: "
					   "got err=%d with null "
					   "or empty referrals\n",
					   op->o_log_prefix,
					   i, rs->sr_err );

				rs->sr_err = LDAP_NO_SUCH_OBJECT;
			}

			/* cleanup */
			ber_memvfree( (void **)references );

			sres = slap_map_api2result( rs );

			if ( candidates[ i ].sr_err == LDAP_SUCCESS ) {
				Debug( LDAP_DEBUG_TRACE, "%s asyncmeta_search_result[%d] "
				       "match=\"%s\" err=%ld",
				       op->o_log_prefix, i,
				       candidates[ i ].sr_matched ? candidates[ i ].sr_matched : "",
				       (long) candidates[ i ].sr_err );
			} else {
					Debug( LDAP_DEBUG_ANY,  "%s asyncmeta_search_result[%d] "
				       "match=\"%s\" err=%ld (%s)",
				       op->o_log_prefix, i,
				       candidates[ i ].sr_matched ? candidates[ i ].sr_matched : "",
					       (long) candidates[ i ].sr_err, ldap_err2string( candidates[ i ].sr_err ) );
			}

			switch ( sres ) {
			case LDAP_NO_SUCH_OBJECT:
				/* is_ok is touched any time a valid
				 * (even intermediate) result is
				 * returned; as a consequence, if
				 * a candidate returns noSuchObject
				 * it is ignored and the candidate
				 * is simply demoted. */
				if ( bc->is_ok ) {
					sres = LDAP_SUCCESS;
				}
				break;

			case LDAP_SUCCESS:
				if ( ctrls != NULL && ctrls[0] != NULL ) {
#ifdef SLAPD_META_CLIENT_PR
					LDAPControl *pr_c;

					pr_c = ldap_control_find( LDAP_CONTROL_PAGEDRESULTS, ctrls, NULL );
					if ( pr_c != NULL ) {
						BerElementBuffer berbuf;
						BerElement *ber = (BerElement *)&berbuf;
						ber_tag_t tag;
						ber_int_t prsize;
						struct berval prcookie;

						/* unsolicited, do not accept */
						if ( mt->mt_ps == 0 ) {
							rs->sr_err = LDAP_OTHER;
							goto err_pr;
						}

						ber_init2( ber, &pr_c->ldctl_value, LBER_USE_DER );

						tag = ber_scanf( ber, "{im}", &prsize, &prcookie );
						if ( tag == LBER_ERROR ) {
							rs->sr_err = LDAP_OTHER;
							goto err_pr;
						}

						/* more pages? new search request */
						if ( !BER_BVISNULL( &prcookie ) && !BER_BVISEMPTY( &prcookie ) ) {
							if ( mt->mt_ps > 0 ) {
								/* ignore size if specified */
								prsize = 0;

							} else if ( prsize == 0 ) {
								/* guess the page size from the entries returned so far */
								prsize = candidates[ i ].sr_nentries;
							}

							candidates[ i ].sr_nentries = 0;
							candidates[ i ].sr_msgid = META_MSGID_IGNORE;
							candidates[ i ].sr_type = REP_INTERMEDIATE;

							assert( candidates[ i ].sr_matched == NULL );
							assert( candidates[ i ].sr_text == NULL );
							assert( candidates[ i ].sr_ref == NULL );

							switch ( asyncmeta_back_search_start( &bc->copy_op, rs, mc, bc, i, &prcookie, prsize, 1 ) )
							{
							case META_SEARCH_CANDIDATE:
								assert( candidates[ i ].sr_msgid >= 0 );
								ldap_controls_free( ctrls );
								//	goto free_message;

							case META_SEARCH_ERR:
							case META_SEARCH_NEED_BIND:
err_pr:;
								candidates[ i ].sr_err = rs->sr_err;
								candidates[ i ].sr_type = REP_RESULT;
								if ( META_BACK_ONERR_STOP( mi ) ) {
									asyncmeta_send_ldap_result(bc, op, rs);
									ldap_controls_free( ctrls );
									goto err_cleanup;
								}
								/* fallthru */

							case META_SEARCH_NOT_CANDIDATE:
								/* means that asyncmeta_back_search_start()
								 * failed but onerr == continue */
								candidates[ i ].sr_msgid = META_MSGID_IGNORE;
								candidates[ i ].sr_type = REP_RESULT;
								break;

							default:
								/* impossible */
								assert( 0 );
								break;
							}
							break;
						}
					}
#endif /* SLAPD_META_CLIENT_PR */

					ldap_controls_free( ctrls );
				}
				/* fallthru */

			case LDAP_REFERRAL:
				bc->is_ok++;
				break;

			case LDAP_SIZELIMIT_EXCEEDED:
				/* if a target returned sizelimitExceeded
				 * and the entry count is equal to the
				 * proxy's limit, the target would have
				 * returned more, and the error must be
				 * propagated to the client; otherwise,
				 * the target enforced a limit lower
				 * than what requested by the proxy;
				 * ignore it */
				candidates[ i ].sr_err = rs->sr_err;
				if ( rs->sr_nentries == op->ors_slimit
					 || META_BACK_ONERR_STOP( mi ) )
				{
					const char *save_text;
got_err:
					save_text = rs->sr_text;
					rs->sr_text = candidates[ i ].sr_text;
					asyncmeta_send_ldap_result(bc, op, rs);
					if (candidates[ i ].sr_text != NULL) {
						ch_free( (char *)candidates[ i ].sr_text );
						candidates[ i ].sr_text = NULL;
					}
					rs->sr_text = save_text;
					ldap_controls_free( ctrls );
					goto err_cleanup;
				}
				break;

			default:
				candidates[ i ].sr_err = rs->sr_err;
				if ( META_BACK_ONERR_STOP( mi ) ) {
					goto got_err;
				}
				break;
			}
			/* if this is the last result we will ever receive, send it back  */
			rc = rs->sr_err;
			if (asyncmeta_is_last_result(mc, bc, i) == 0) {
				Debug( LDAP_DEBUG_TRACE,
					"%s asyncmeta_handle_search_msg: msc %p last result\n",
					op->o_log_prefix, msc );
				asyncmeta_search_last_result(mc, bc, i, sres);
err_cleanup:
				rc = rs->sr_err;
				ldap_pvt_thread_mutex_lock( &mc->mc_om_mutex );
				asyncmeta_drop_bc( mc, bc);
				asyncmeta_clear_bm_context(bc);
				ldap_pvt_thread_mutex_unlock( &mc->mc_om_mutex );
				ldap_msgfree(res);
				return rc;
			}
finish:
			break;

		default:
			continue;
		}
	}
		ldap_msgfree(res);
		res = NULL;
		if (candidates[ i ].sr_type != REP_RESULT) {
			struct timeval	tv = {0};
			rc = ldap_result( msc->msc_ldr, id, LDAP_MSG_RECEIVED, &tv, &res );
			if (res != NULL) {
				msc->msc_result_time = slap_get_time();
			}
		}
	}
	ldap_pvt_thread_mutex_lock( &mc->mc_om_mutex );
	bc->bc_active--;
	ldap_pvt_thread_mutex_unlock( &mc->mc_om_mutex );

	return rc;
}
Example #24
0
int ber_decode_krb5_key_data(struct berval *encoded, int *m_kvno,
                             int *numk, krb5_key_data **data)
{
    krb5_key_data *keys = NULL;
    BerElement *be = NULL;
    void *tmp;
    int i = 0;
    ber_tag_t tag;
    ber_int_t major_vno;
    ber_int_t minor_vno;
    ber_int_t kvno;
    ber_int_t mkvno;
    ber_int_t type;
    ber_tag_t seqtag;
    ber_len_t seqlen;
    ber_len_t setlen;
    ber_tag_t retag;
    ber_tag_t opttag;
    struct berval tval;
    int ret;

    be = ber_alloc_t(LBER_USE_DER);
    if (!be) {
        return ENOMEM;
    }

    /* reinit the ber element with the new val */
    ber_init2(be, encoded, LBER_USE_DER);

    /* fill key_data struct with the data */
    retag = ber_scanf(be, "{t[i]t[i]t[i]t[i]t[{",
                      &tag, &major_vno,
                      &tag, &minor_vno,
                      &tag, &kvno,
                      &tag, &mkvno,
                      &seqtag);
    if (retag == LBER_ERROR ||
            major_vno != 1 ||
            minor_vno != 1 ||
            seqtag != (LBER_CONSTRUCTED | LBER_CLASS_CONTEXT | 4)) {
        ret = EINVAL;
        goto done;
    }

    retag = ber_skip_tag(be, &seqlen);

    /* sequence of keys */
    for (i = 0; retag == LBER_SEQUENCE; i++) {

        tmp = realloc(keys, (i + 1) * sizeof(krb5_key_data));
        if (!tmp) {
            ret = ENOMEM;
            goto done;
        }
        keys = tmp;

        memset(&keys[i], 0, sizeof(krb5_key_data));

        keys[i].key_data_kvno = kvno;

        /* do we have a salt type ? (optional) */
        retag = ber_scanf(be, "t", &opttag);
        if (retag == LBER_ERROR) {
            ret = EINVAL;
            goto done;
        }
        if (opttag == (LBER_CONSTRUCTED | LBER_CLASS_CONTEXT | 0)) {
            keys[i].key_data_ver = 2;

            retag = ber_scanf(be, "[l{tl[i]",
                              &seqlen, &tag, &setlen, &type);
            if (tag != (LBER_CONSTRUCTED | LBER_CLASS_CONTEXT | 0)) {
                ret = EINVAL;
                goto done;
            }
            keys[i].key_data_type[1] = type;

            /* do we have salt data ? (optional) */
            if (seqlen > setlen + 2) {
                retag = ber_scanf(be, "t[o]", &tag, &tval);
                if (retag == LBER_ERROR ||
                    tag != (LBER_CONSTRUCTED | LBER_CLASS_CONTEXT | 1)) {
                    ret = EINVAL;
                    goto done;
                }
                keys[i].key_data_length[1] = tval.bv_len;
                keys[i].key_data_contents[1] = (krb5_octet *)tval.bv_val;
            }

            retag = ber_scanf(be, "}]t", &opttag);
            if (retag == LBER_ERROR) {
                ret = EINVAL;
                goto done;
            }

        } else {
            keys[i].key_data_ver = 1;
        }

        if (opttag != (LBER_CONSTRUCTED | LBER_CLASS_CONTEXT | 1)) {
            ret = EINVAL;
            goto done;
        }

        /* get the key */
        retag = ber_scanf(be, "[{t[i]t[o]}]", &tag, &type, &tag, &tval);
        if (retag == LBER_ERROR) {
            ret = EINVAL;
            goto done;
        }
        keys[i].key_data_type[0] = type;
        keys[i].key_data_length[0] = tval.bv_len;
        keys[i].key_data_contents[0] = (krb5_octet *)tval.bv_val;

        /* check for sk2params */
        retag = ber_peek_tag(be, &setlen);
        if (retag == (LBER_CONSTRUCTED | LBER_CLASS_CONTEXT | 2)) {
            /* not supported yet, skip */
            retag = ber_scanf(be, "t[x]}");
        } else {
            retag = ber_scanf(be, "}");
        }
        if (retag == LBER_ERROR) {
            ret = EINVAL;
            goto done;
        }

        retag = ber_skip_tag(be, &seqlen);
    }

    ret = 0;

done:
    ber_free(be, 0); /* internal buffer is 'encoded' */
    if (ret) {
        for (i -= 1; keys && i >= 0; i--) {
            free(keys[i].key_data_contents[0]);
            free(keys[i].key_data_contents[1]);
        }
        free(keys);
        keys = NULL;
        mkvno = 0;
    }
    *m_kvno = mkvno;
    *numk = i;
    *data = keys;
    return ret;
}
Example #25
0
int slap_passwd_parse( struct berval *reqdata,
                       struct berval *id,
                       struct berval *oldpass,
                       struct berval *newpass,
                       const char **text )
{
    int rc = LDAP_SUCCESS;
    ber_tag_t tag;
    ber_len_t len;
    char berbuf[LBER_ELEMENT_SIZEOF];
    BerElement *ber = (BerElement *)berbuf;

    if( reqdata == NULL ) {
        return LDAP_SUCCESS;
    }

    if( reqdata->bv_len == 0 ) {
        *text = "empty request data field";
        return LDAP_PROTOCOL_ERROR;
    }

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

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

    if( tag != LBER_ERROR ) {
        tag = ber_peek_tag( ber, &len );
    }

    if( tag == LDAP_TAG_EXOP_MODIFY_PASSWD_ID ) {
        if( id == NULL ) {
#ifdef NEW_LOGGING
            LDAP_LOG( OPERATION, ERR,
                      "slap_passwd_parse: ID not allowed.\n", 0, 0, 0 );
#else
            Debug( LDAP_DEBUG_TRACE, "slap_passwd_parse: ID not allowed.\n",
                   0, 0, 0 );
#endif

            *text = "user must change own password";
            rc = LDAP_UNWILLING_TO_PERFORM;
            goto done;
        }

        tag = ber_scanf( ber, "m", id );

        if( tag == LBER_ERROR ) {
#ifdef NEW_LOGGING
            LDAP_LOG( OPERATION, ERR,
                      "slap_passwd_parse:  ID parse failed.\n", 0, 0, 0 );
#else
            Debug( LDAP_DEBUG_TRACE, "slap_passwd_parse: ID parse failed.\n",
                   0, 0, 0 );
#endif

            goto decoding_error;
        }

        tag = ber_peek_tag( ber, &len);
    }

    if( tag == LDAP_TAG_EXOP_MODIFY_PASSWD_OLD ) {
        if( oldpass == NULL ) {
#ifdef NEW_LOGGING
            LDAP_LOG( OPERATION, ERR,
                      "slap_passwd_parse: OLD not allowed.\n" , 0, 0, 0 );
#else
            Debug( LDAP_DEBUG_TRACE, "slap_passwd_parse: OLD not allowed.\n",
                   0, 0, 0 );
#endif

            *text = "use bind to verify old password";
            rc = LDAP_UNWILLING_TO_PERFORM;
            goto done;
        }

        tag = ber_scanf( ber, "m", oldpass );

        if( tag == LBER_ERROR ) {
#ifdef NEW_LOGGING
            LDAP_LOG( OPERATION, ERR,
                      "slap_passwd_parse:  ID parse failed.\n" , 0, 0, 0 );
#else
            Debug( LDAP_DEBUG_TRACE, "slap_passwd_parse: ID parse failed.\n",
                   0, 0, 0 );
#endif

            goto decoding_error;
        }

        tag = ber_peek_tag( ber, &len );
    }

    if( tag == LDAP_TAG_EXOP_MODIFY_PASSWD_NEW ) {
        if( newpass == NULL ) {
#ifdef NEW_LOGGING
            LDAP_LOG( OPERATION, ERR,
                      "slap_passwd_parse:  NEW not allowed.\n", 0, 0, 0 );
#else
            Debug( LDAP_DEBUG_TRACE, "slap_passwd_parse: NEW not allowed.\n",
                   0, 0, 0 );
#endif

            *text = "user specified passwords disallowed";
            rc = LDAP_UNWILLING_TO_PERFORM;
            goto done;
        }

        tag = ber_scanf( ber, "m", newpass );

        if( tag == LBER_ERROR ) {
#ifdef NEW_LOGGING
            LDAP_LOG( OPERATION, ERR,
                      "slap_passwd_parse:  OLD parse failed.\n", 0, 0, 0 );
#else
            Debug( LDAP_DEBUG_TRACE, "slap_passwd_parse: OLD parse failed.\n",
                   0, 0, 0 );
#endif

            goto decoding_error;
        }

        tag = ber_peek_tag( ber, &len );
    }

    if( len != 0 ) {
decoding_error:
#ifdef NEW_LOGGING
        LDAP_LOG( OPERATION, ERR,
                  "slap_passwd_parse: decoding error, len=%ld\n", (long)len, 0, 0 );
#else
        Debug( LDAP_DEBUG_TRACE,
               "slap_passwd_parse: decoding error, len=%ld\n",
               (long) len, 0, 0 );
#endif

        *text = "data decoding error";
        rc = LDAP_PROTOCOL_ERROR;
    }

done:
    return rc;
}
Example #26
0
File: vc.c Project: Joywar/openldap
static int
vc_exop(
	Operation	*op,
	SlapReply	*rs )
{
	int rc = LDAP_SUCCESS;
	ber_tag_t tag;
	ber_len_t len = -1;
	BerElementBuffer berbuf;
	BerElement *ber = (BerElement *)&berbuf;
	struct berval reqdata = BER_BVNULL;

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

	} else {
		void *thrctx;

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

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

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

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

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

	switch ( authtag ) {
	case LDAP_AUTH_SIMPLE:
		break;

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

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

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

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

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

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

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

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

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

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

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

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

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

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

        return rs->sr_err;
}
Example #27
0
File: vc.c Project: 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;
}
Example #28
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 );

}
Example #29
0
int txn_end_extop(
	Operation *op, SlapReply *rs )
{
	int rc;
	BerElementBuffer berbuf;
	BerElement *ber = (BerElement *)&berbuf;
	ber_tag_t tag;
	ber_len_t len;
	ber_int_t commit=1;
	struct berval txnid;

	Statslog( LDAP_DEBUG_STATS, "%s TXN END\n",
		op->o_log_prefix, 0, 0, 0, 0 );

	if( op->ore_reqdata == NULL ) {
		rs->sr_text = "request data expected";
		return LDAP_PROTOCOL_ERROR;
	}
	if( op->ore_reqdata->bv_len == 0 ) {
		rs->sr_text = "empty request data";
		return LDAP_PROTOCOL_ERROR;
	}

	op->o_bd = op->o_conn->c_authz_backend;
	if( backend_check_restrictions( op, rs,
		(struct berval *)&slap_EXOP_TXN_END ) != LDAP_SUCCESS )
	{
		return rs->sr_err;
	}

	ber_init2( ber, op->ore_reqdata, 0 );

	tag = ber_scanf( ber, "{" /*}*/ );
	if( tag == LBER_ERROR ) {
		rs->sr_text = "request data decoding error";
		return LDAP_PROTOCOL_ERROR;
	}

	tag = ber_peek_tag( ber, &len );
	if( tag == LBER_BOOLEAN ) {
		tag = ber_scanf( ber, "b", &commit );
		if( tag == LBER_ERROR ) {
			rs->sr_text = "request data decoding error";
			return LDAP_PROTOCOL_ERROR;
		}
	}

	tag = ber_scanf( ber, /*{*/ "m}", &txnid );
	if( tag == LBER_ERROR ) {
		rs->sr_text = "request data decoding error";
		return LDAP_PROTOCOL_ERROR;
	}

	if( txnid.bv_len ) {
		rs->sr_text = "invalid transaction identifier";
		return LDAP_X_TXN_ID_INVALID;
	}

	/* acquire connection lock */
	ldap_pvt_thread_mutex_lock( &op->o_conn->c_mutex );

	if( op->o_conn->c_txn != CONN_TXN_SPECIFY ) {
		rs->sr_text = "invalid transaction identifier";
		rc = LDAP_X_TXN_ID_INVALID;
		goto done;
	}
	op->o_conn->c_txn = CONN_TXN_SETTLE;

	if( commit ) {
		if ( op->o_abandon ) {
		}

		if( LDAP_STAILQ_EMPTY(&op->o_conn->c_txn_ops) ) {
			/* no updates to commit */
			rs->sr_text = "no updates to commit";
			rc = LDAP_OPERATIONS_ERROR;
			goto settled;
		}

		rs->sr_text = "not yet implemented";
		rc = LDAP_UNWILLING_TO_PERFORM;

	} else {
		rs->sr_text = "transaction aborted";
		rc = LDAP_SUCCESS;;
	}

drain:
	/* drain txn ops list */

settled:
	assert( LDAP_STAILQ_EMPTY(&op->o_conn->c_txn_ops) );
	assert( op->o_conn->c_txn == CONN_TXN_SETTLE );
	op->o_conn->c_txn = CONN_TXN_INACTIVE;
	op->o_conn->c_txn_backend = NULL;

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

	return rc;
}
Example #30
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;
}