+#ifdef LDAP_DEBUG
+ filter2bv_x( op, op->o_assertion, &fstr );
+
+#ifdef NEW_LOGGING
+ LDAP_LOG( OPERATION, ARGS,
+ "parseAssert: conn %ld assert: %s\n",
+ op->o_connid, fstr.bv_len ? fstr.bv_val : "empty" , 0 );
+#else
+ Debug( LDAP_DEBUG_ARGS, "parseAssert: conn %ld assert: %s\n",
+ op->o_connid, fstr.bv_len ? fstr.bv_val : "empty" , 0 );
+#endif
+ op->o_tmpfree( fstr.bv_val, op->o_tmpmemctx );
+#endif
+
+ op->o_assert = ctrl->ldctl_iscritical
+ ? SLAP_CRITICAL_CONTROL
+ : SLAP_NONCRITICAL_CONTROL;
+
+ rs->sr_err = LDAP_SUCCESS;
+ return LDAP_SUCCESS;
+}
+
+static int parsePreRead (
+ Operation *op,
+ SlapReply *rs,
+ LDAPControl *ctrl )
+{
+ ber_len_t siz, off, i;
+ AttributeName *an = NULL;
+ BerElement *ber;
+
+ if ( op->o_preread != SLAP_NO_CONTROL ) {
+ rs->sr_text = "preread control specified multiple times";
+ return LDAP_PROTOCOL_ERROR;
+ }
+
+ if ( ctrl->ldctl_value.bv_len == 0 ) {
+ rs->sr_text = "preread control value is empty (or absent)";
+ return LDAP_PROTOCOL_ERROR;
+ }
+
+ ber = ber_init( &(ctrl->ldctl_value) );
+ if (ber == NULL) {
+ rs->sr_text = "preread control: internal error";
+ return LDAP_OTHER;
+ }
+
+ siz = sizeof( AttributeName );
+ off = offsetof( AttributeName, an_name );
+ if ( ber_scanf( ber, "{M}", &an, &siz, off ) == LBER_ERROR ) {
+ rs->sr_text = "preread control: decoding error";
+ return LDAP_PROTOCOL_ERROR;
+ }
+
+ for( i=0; i<siz; i++ ) {
+ int rc = LDAP_SUCCESS;
+ const char *dummy = NULL;
+
+ an[i].an_desc = NULL;
+ an[i].an_oc = NULL;
+ an[i].an_oc_exclude = 0;
+ rc = slap_bv2ad( &an[i].an_name, &an[i].an_desc, &dummy );
+ if ( rc != LDAP_SUCCESS && ctrl->ldctl_iscritical ) {
+ rs->sr_text = dummy ? dummy : "postread control: unknown attributeType";
+ return rc;
+ }
+ }
+
+ op->o_preread = ctrl->ldctl_iscritical
+ ? SLAP_CRITICAL_CONTROL
+ : SLAP_NONCRITICAL_CONTROL;
+
+ op->o_preread_attrs = an;
+
+ rs->sr_err = LDAP_SUCCESS;
+ return LDAP_SUCCESS;
+}
+
+static int parsePostRead (
+ Operation *op,
+ SlapReply *rs,
+ LDAPControl *ctrl )
+{
+ ber_len_t siz, off, i;
+ AttributeName *an = NULL;
+ BerElement *ber;
+
+ if ( op->o_postread != SLAP_NO_CONTROL ) {
+ rs->sr_text = "postread control specified multiple times";
+ return LDAP_PROTOCOL_ERROR;
+ }
+
+ if ( ctrl->ldctl_value.bv_len == 0 ) {
+ rs->sr_text = "postread control value is empty (or absent)";
+ return LDAP_PROTOCOL_ERROR;
+ }
+
+ ber = ber_init( &(ctrl->ldctl_value) );
+ if (ber == NULL) {
+ rs->sr_text = "postread control: internal error";
+ return LDAP_OTHER;
+ }
+
+ siz = sizeof( AttributeName );
+ off = offsetof( AttributeName, an_name );
+ if ( ber_scanf( ber, "{M}", &an, &siz, off ) == LBER_ERROR ) {
+ rs->sr_text = "postread control: decoding error";
+ return LDAP_PROTOCOL_ERROR;
+ }
+
+ for( i=0; i<siz; i++ ) {
+ int rc = LDAP_SUCCESS;
+ const char *dummy = NULL;
+
+ an[i].an_desc = NULL;
+ an[i].an_oc = NULL;
+ an[i].an_oc_exclude = 0;
+ rc = slap_bv2ad( &an[i].an_name, &an[i].an_desc, &dummy );
+ if ( rc != LDAP_SUCCESS && ctrl->ldctl_iscritical ) {
+ rs->sr_text = dummy ? dummy : "postread control: unknown attributeType";
+ return rc;
+ }
+ }
+
+ op->o_postread = ctrl->ldctl_iscritical
+ ? SLAP_CRITICAL_CONTROL
+ : SLAP_NONCRITICAL_CONTROL;
+
+ op->o_postread_attrs = an;
+
+ rs->sr_err = LDAP_SUCCESS;
+ return LDAP_SUCCESS;
+}
+
+int parseValuesReturnFilter (
+ Operation *op,
+ SlapReply *rs,
+ LDAPControl *ctrl )
+{
+ BerElement *ber;
+ struct berval fstr = { 0, NULL };
+ const char *err_msg = "";
+
+ if ( op->o_valuesreturnfilter != SLAP_NO_CONTROL ) {
+ rs->sr_text = "valuesReturnFilter control specified multiple times";
+ return LDAP_PROTOCOL_ERROR;
+ }
+
+ if ( ctrl->ldctl_value.bv_len == 0 ) {
+ rs->sr_text = "valuesReturnFilter control value is empty (or absent)";
+ return LDAP_PROTOCOL_ERROR;
+ }
+
+ ber = ber_init( &(ctrl->ldctl_value) );
+ if (ber == NULL) {
+ rs->sr_text = "internal error";
+ return LDAP_OTHER;
+ }
+
+ rs->sr_err = get_vrFilter( op, ber, &(op->o_vrFilter), &rs->sr_text);
+
+ if( rs->sr_err != LDAP_SUCCESS ) {
+ if( rs->sr_err == SLAPD_DISCONNECT ) {
+ rs->sr_err = LDAP_PROTOCOL_ERROR;
+ send_ldap_disconnect( op, rs );
+ rs->sr_err = SLAPD_DISCONNECT;
+ } else {
+ send_ldap_result( op, rs );
+ }
+ if( op->o_vrFilter != NULL) vrFilter_free( op, op->o_vrFilter );
+ }
+#ifdef LDAP_DEBUG
+ else {
+ vrFilter2bv( op, op->o_vrFilter, &fstr );
+ }
+
+#ifdef NEW_LOGGING
+ LDAP_LOG( OPERATION, ARGS,
+ "parseValuesReturnFilter: conn %d vrFilter: %s\n",
+ op->o_connid, fstr.bv_len ? fstr.bv_val : "empty" , 0 );
+#else
+ Debug( LDAP_DEBUG_ARGS, " vrFilter: %s\n",
+ fstr.bv_len ? fstr.bv_val : "empty", 0, 0 );
+#endif
+ op->o_tmpfree( fstr.bv_val, op->o_tmpmemctx );
+#endif
+
+ op->o_valuesreturnfilter = ctrl->ldctl_iscritical
+ ? SLAP_CRITICAL_CONTROL
+ : SLAP_NONCRITICAL_CONTROL;
+
+ rs->sr_err = LDAP_SUCCESS;
+ return LDAP_SUCCESS;
+}
+
+#ifdef LDAP_CONTROL_SUBENTRIES
+static int parseSubentries (
+ Operation *op,
+ SlapReply *rs,
+ LDAPControl *ctrl )
+{
+ if ( op->o_subentries != SLAP_NO_CONTROL ) {
+ rs->sr_text = "subentries control specified multiple times";
+ return LDAP_PROTOCOL_ERROR;
+ }
+
+ /* FIXME: should use BER library */
+ if( ( ctrl->ldctl_value.bv_len != 3 )
+ && ( ctrl->ldctl_value.bv_val[0] != 0x01 )
+ && ( ctrl->ldctl_value.bv_val[1] != 0x01 ))
+ {
+ rs->sr_text = "subentries control value encoding is bogus";
+ return LDAP_PROTOCOL_ERROR;
+ }
+
+ op->o_subentries = ctrl->ldctl_iscritical
+ ? SLAP_CRITICAL_CONTROL
+ : SLAP_NONCRITICAL_CONTROL;
+
+ op->o_subentries_visibility = (ctrl->ldctl_value.bv_val[2] != 0x00);
+
+ return LDAP_SUCCESS;
+}
+#endif
+
+#ifdef LDAP_CONTROL_X_PERMISSIVE_MODIFY
+static int parsePermissiveModify (
+ Operation *op,
+ SlapReply *rs,
+ LDAPControl *ctrl )
+{
+ if ( op->o_permissive_modify != SLAP_NO_CONTROL ) {
+ rs->sr_text = "permissiveModify control specified multiple times";
+ return LDAP_PROTOCOL_ERROR;
+ }
+
+ if ( ctrl->ldctl_value.bv_len ) {
+ rs->sr_text = "permissiveModify control value not empty";
+ return LDAP_PROTOCOL_ERROR;
+ }
+
+ op->o_permissive_modify = ctrl->ldctl_iscritical
+ ? SLAP_CRITICAL_CONTROL
+ : SLAP_NONCRITICAL_CONTROL;
+
+ return LDAP_SUCCESS;
+}
+#endif
+
+#ifdef LDAP_CONTROL_X_DOMAIN_SCOPE
+static int parseDomainScope (
+ Operation *op,
+ SlapReply *rs,
+ LDAPControl *ctrl )
+{
+ if ( op->o_domain_scope != SLAP_NO_CONTROL ) {
+ rs->sr_text = "domainScope control specified multiple times";
+ return LDAP_PROTOCOL_ERROR;
+ }
+
+ if ( ctrl->ldctl_value.bv_len ) {
+ rs->sr_text = "domainScope control value not empty";
+ return LDAP_PROTOCOL_ERROR;
+ }
+
+ op->o_domain_scope = ctrl->ldctl_iscritical
+ ? SLAP_CRITICAL_CONTROL
+ : SLAP_NONCRITICAL_CONTROL;
+
+ return LDAP_SUCCESS;
+}
+#endif
+
+static int parseLDAPsync (
+ Operation *op,
+ SlapReply *rs,
+ LDAPControl *ctrl )
+{
+ ber_tag_t tag;
+ BerElement *ber;
+ ber_int_t mode;
+ ber_len_t len;
+ struct slap_session_entry *se;
+
+ if ( op->o_sync != SLAP_NO_CONTROL ) {
+ rs->sr_text = "LDAP Sync control specified multiple times";
+ return LDAP_PROTOCOL_ERROR;
+ }
+
+ if ( ctrl->ldctl_value.bv_len == 0 ) {
+ rs->sr_text = "LDAP Sync control value is empty (or absent)";
+ return LDAP_PROTOCOL_ERROR;
+ }
+
+ /* Parse the control value
+ * syncRequestValue ::= SEQUENCE {
+ * mode ENUMERATED {
+ * -- 0 unused
+ * refreshOnly (1),
+ * -- 2 reserved
+ * refreshAndPersist (3)
+ * },
+ * cookie syncCookie OPTIONAL
+ * }
+ */
+
+ ber = ber_init( &ctrl->ldctl_value );
+ if( ber == NULL ) {
+ rs->sr_text = "internal error";
+ return LDAP_OTHER;
+ }
+
+ if ( (tag = ber_scanf( ber, "{i" /*}*/, &mode )) == LBER_ERROR ) {
+ rs->sr_text = "LDAP Sync control : mode decoding error";
+ return LDAP_PROTOCOL_ERROR;
+ }
+
+ switch( mode ) {
+ case LDAP_SYNC_REFRESH_ONLY:
+ mode = SLAP_SYNC_REFRESH;
+ break;
+ case LDAP_SYNC_REFRESH_AND_PERSIST:
+ mode = SLAP_SYNC_REFRESH_AND_PERSIST;
+ break;
+ default:
+ rs->sr_text = "LDAP Sync control : unknown update mode";
+ return LDAP_PROTOCOL_ERROR;
+ }
+
+ tag = ber_peek_tag( ber, &len );
+
+ if ( tag == LDAP_TAG_SYNC_COOKIE ) {
+ struct berval tmp_bv;
+ if (( ber_scanf( ber, /*{*/ "o", &tmp_bv )) == LBER_ERROR ) {
+ rs->sr_text = "LDAP Sync control : cookie decoding error";
+ return LDAP_PROTOCOL_ERROR;
+ }
+ ber_bvarray_add( &op->o_sync_state.octet_str, &tmp_bv );
+ slap_parse_sync_cookie( &op->o_sync_state );
+ }
+ if ( tag == LDAP_TAG_RELOAD_HINT ) {
+ if (( ber_scanf( ber, /*{*/ "b", &op->o_sync_rhint )) == LBER_ERROR ) {
+ rs->sr_text = "LDAP Sync control : rhint decoding error";
+ return LDAP_PROTOCOL_ERROR;
+ }
+ }
+ if (( ber_scanf( ber, /*{*/ "}")) == LBER_ERROR ) {
+ rs->sr_text = "LDAP Sync control : decoding error";
+ return LDAP_PROTOCOL_ERROR;
+ }
+
+ (void) ber_free( ber, 1 );
+
+ op->o_sync_mode = (char) mode;
+
+ op->o_sync = ctrl->ldctl_iscritical
+ ? SLAP_CRITICAL_CONTROL
+ : SLAP_NONCRITICAL_CONTROL;
+
+ return LDAP_SUCCESS;