X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;ds=sidebyside;f=servers%2Fslapd%2Fcontrols.c;h=1900312250e856026279a1b2e7cc95c3ee3255e9;hb=89812424f4f844053cc2607e3e5e9382b0825bb8;hp=7e4d9af3ed9db04d2fd66fe5149cf362e16f0c31;hpb=46a841870fe6cce3108ef32019b8b3d9ff62edec;p=openldap diff --git a/servers/slapd/controls.c b/servers/slapd/controls.c index 7e4d9af3ed..1900312250 100644 --- a/servers/slapd/controls.c +++ b/servers/slapd/controls.c @@ -1,13 +1,18 @@ /* $OpenLDAP$ */ -/* - * Copyright 1999-2003 The OpenLDAP Foundation. +/* This work is part of OpenLDAP Software . + * + * Copyright 1998-2004 The OpenLDAP Foundation. * All rights reserved. * - * Redistribution and use in source and binary forms are permitted only - * as authorized by the OpenLDAP Public License. A copy of this - * license is available at http://www.OpenLDAP.org/license.html or - * in file LICENSE in the top-level directory of the distribution. + * Redistribution and use in source and binary forms, with or without + * modification, are permitted only as authorized by the OpenLDAP + * Public License. + * + * A copy of this license is available in the file LICENSE in the + * top-level directory of the distribution or, alternatively, at + * . */ + #include "portable.h" #include @@ -19,8 +24,12 @@ #include "../../libraries/liblber/lber-int.h" +static SLAP_CTRL_PARSE_FN parseAssert; +static SLAP_CTRL_PARSE_FN parsePreRead; +static SLAP_CTRL_PARSE_FN parsePostRead; static SLAP_CTRL_PARSE_FN parseProxyAuthz; static SLAP_CTRL_PARSE_FN parseManageDSAit; +static SLAP_CTRL_PARSE_FN parseModifyIncrement; static SLAP_CTRL_PARSE_FN parseNoOp; static SLAP_CTRL_PARSE_FN parsePagedResults; static SLAP_CTRL_PARSE_FN parseValuesReturnFilter; @@ -30,40 +39,24 @@ static SLAP_CTRL_PARSE_FN parseDomainScope; #ifdef LDAP_CONTROL_SUBENTRIES static SLAP_CTRL_PARSE_FN parseSubentries; #endif -#ifdef LDAP_CLIENT_UPDATE -static SLAP_CTRL_PARSE_FN parseClientUpdate; -#endif -#ifdef LDAP_SYNC -static SLAP_CTRL_PARSE_FN parseLdupSync; -#endif +static SLAP_CTRL_PARSE_FN parseLDAPsync; #undef sc_mask /* avoid conflict with Irix 6.5 */ -static char *proxy_authz_extops[] = { - LDAP_EXOP_MODIFY_PASSWD, - LDAP_EXOP_X_WHO_AM_I, - NULL -}; +const struct berval slap_pre_read_bv = BER_BVC(LDAP_CONTROL_PRE_READ); +const struct berval slap_post_read_bv = BER_BVC(LDAP_CONTROL_POST_READ); struct slap_control { - /* - * Control OID - */ + /* Control OID */ char *sc_oid; - /* - * Operations supported by control - */ + /* Operations supported by control */ slap_mask_t sc_mask; - /* - * Extended operations supported by control - */ + /* Extended operations supported by control */ char **sc_extendedops; - /* - * Control parsing callback - */ + /* Control parsing callback */ SLAP_CTRL_PARSE_FN *sc_parse; LDAP_SLIST_ENTRY(slap_control) sc_next; @@ -77,50 +70,61 @@ static LDAP_SLIST_HEAD(ControlsList, slap_control) controls_list */ char **slap_known_controls = NULL; +static char *proxy_authz_extops[] = { + LDAP_EXOP_MODIFY_PASSWD, + LDAP_EXOP_X_WHO_AM_I, + NULL +}; + static struct slap_control control_defs[] = { + { LDAP_CONTROL_ASSERT, + SLAP_CTRL_HIDE|SLAP_CTRL_ACCESS, NULL, + parseAssert, LDAP_SLIST_ENTRY_INITIALIZER(next) }, + { LDAP_CONTROL_PRE_READ, + SLAP_CTRL_HIDE|SLAP_CTRL_DELETE|SLAP_CTRL_MODIFY|SLAP_CTRL_RENAME, NULL, + parsePreRead, LDAP_SLIST_ENTRY_INITIALIZER(next) }, + { LDAP_CONTROL_POST_READ, + SLAP_CTRL_HIDE|SLAP_CTRL_ADD|SLAP_CTRL_MODIFY|SLAP_CTRL_RENAME, NULL, + parsePostRead, LDAP_SLIST_ENTRY_INITIALIZER(next) }, { LDAP_CONTROL_VALUESRETURNFILTER, SLAP_CTRL_SEARCH, NULL, - parseValuesReturnFilter, LDAP_SLIST_NEXT_INITIALIZER(next) }, -#ifdef LDAP_CONTROL_PAGEDRESULTS + parseValuesReturnFilter, LDAP_SLIST_ENTRY_INITIALIZER(next) }, { LDAP_CONTROL_PAGEDRESULTS, SLAP_CTRL_SEARCH, NULL, - parsePagedResults, LDAP_SLIST_NEXT_INITIALIZER(next) }, -#endif + parsePagedResults, LDAP_SLIST_ENTRY_INITIALIZER(next) }, #ifdef LDAP_CONTROL_X_DOMAIN_SCOPE { LDAP_CONTROL_X_DOMAIN_SCOPE, SLAP_CTRL_FRONTEND|SLAP_CTRL_SEARCH, NULL, - parseDomainScope, LDAP_SLIST_NEXT_INITIALIZER(next) }, + parseDomainScope, LDAP_SLIST_ENTRY_INITIALIZER(next) }, #endif #ifdef LDAP_CONTROL_X_PERMISSIVE_MODIFY { LDAP_CONTROL_X_PERMISSIVE_MODIFY, SLAP_CTRL_MODIFY, NULL, - parsePermissiveModify, LDAP_SLIST_NEXT_INITIALIZER(next) }, + parsePermissiveModify, LDAP_SLIST_ENTRY_INITIALIZER(next) }, #endif #ifdef LDAP_CONTROL_SUBENTRIES { LDAP_CONTROL_SUBENTRIES, SLAP_CTRL_SEARCH, NULL, - parseSubentries, LDAP_SLIST_NEXT_INITIALIZER(next) }, + parseSubentries, LDAP_SLIST_ENTRY_INITIALIZER(next) }, #endif { LDAP_CONTROL_NOOP, SLAP_CTRL_ACCESS, NULL, - parseNoOp, LDAP_SLIST_NEXT_INITIALIZER(next) }, -#ifdef LDAP_CLIENT_UPDATE - { LDAP_CONTROL_CLIENT_UPDATE, - SLAP_CTRL_SEARCH, NULL, - parseClientUpdate, LDAP_SLIST_NEXT_INITIALIZER(next) }, -#endif -#ifdef LDAP_SYNC + parseNoOp, LDAP_SLIST_ENTRY_INITIALIZER(next) }, { LDAP_CONTROL_SYNC, - SLAP_CTRL_SEARCH, NULL, - parseLdupSync, LDAP_SLIST_NEXT_INITIALIZER(next) }, + SLAP_CTRL_HIDE|SLAP_CTRL_SEARCH, NULL, + parseLDAPsync, LDAP_SLIST_ENTRY_INITIALIZER(next) }, +#ifdef LDAP_CONTROL_MODIFY_INCREMENT + { LDAP_CONTROL_MODIFY_INCREMENT, + SLAP_CTRL_HIDE|SLAP_CTRL_MODIFY, NULL, + parseModifyIncrement, LDAP_SLIST_ENTRY_INITIALIZER(next) }, #endif { LDAP_CONTROL_MANAGEDSAIT, SLAP_CTRL_ACCESS, NULL, - parseManageDSAit, LDAP_SLIST_NEXT_INITIALIZER(next) }, + parseManageDSAit, LDAP_SLIST_ENTRY_INITIALIZER(next) }, { LDAP_CONTROL_PROXY_AUTHZ, SLAP_CTRL_FRONTEND|SLAP_CTRL_ACCESS, proxy_authz_extops, - parseProxyAuthz, LDAP_SLIST_NEXT_INITIALIZER(next) }, - { NULL, 0, NULL, 0, LDAP_SLIST_NEXT_INITIALIZER(next) } + parseProxyAuthz, LDAP_SLIST_ENTRY_INITIALIZER(next) }, + { NULL, 0, NULL, 0, LDAP_SLIST_ENTRY_INITIALIZER(next) } }; /* @@ -226,7 +230,9 @@ controls_destroy( void ) if ( sc->sc_extendedops != NULL ) { ldap_charray_free( sc->sc_extendedops ); } + ch_free( sc ); } + ldap_charray_free( slap_known_controls ); } /* @@ -246,14 +252,14 @@ controls_root_dse_info( Entry *e ) vals[1].bv_len = 0; LDAP_SLIST_FOREACH( sc, &controls_list, sc_next ) { + if( sc->sc_mask & SLAP_CTRL_HIDE ) continue; + vals[0].bv_val = sc->sc_oid; vals[0].bv_len = strlen( sc->sc_oid ); -#ifdef SLAP_NVALUES - if ( attr_merge( e, ad_supportedControl, vals, NULL ) ) -#else - if ( attr_merge( e, ad_supportedControl, vals ) ) -#endif /* SLAP_NVALUES */ + + if ( attr_merge( e, ad_supportedControl, vals, NULL ) ) { return -1; + } } return 0; @@ -328,9 +334,22 @@ find_ctrl( const char *oid ) return NULL; } +void slap_free_ctrls( + Operation *op, + LDAPControl **ctrls +) +{ + int i; + + for (i=0; ctrls[i]; i++) { + op->o_tmpfree(ctrls[i], op->o_tmpmemctx ); + } + op->o_tmpfree( ctrls, op->o_tmpmemctx ); +} + int get_ctrls( - Connection *conn, Operation *op, + SlapReply *rs, int sendres ) { int nctrls = 0; @@ -339,21 +358,20 @@ int get_ctrls( char *opaque; BerElement *ber = op->o_ber; struct slap_control *sc; - int rc = LDAP_SUCCESS; - const char *errmsg = NULL; + struct berval bv; len = ber_pvt_ber_remaining(ber); if( len == 0) { /* no controls */ - rc = LDAP_SUCCESS; - return rc; + rs->sr_err = LDAP_SUCCESS; + return rs->sr_err; } if(( tag = ber_peek_tag( ber, &len )) != LDAP_TAG_CONTROLS ) { if( tag == LBER_ERROR ) { - rc = SLAPD_DISCONNECT; - errmsg = "unexpected data in PDU"; + rs->sr_err = SLAPD_DISCONNECT; + rs->sr_text = "unexpected data in PDU"; } goto return_results; @@ -361,25 +379,25 @@ int get_ctrls( #ifdef NEW_LOGGING LDAP_LOG( OPERATION, ENTRY, - "get_ctrls: conn %lu\n", conn->c_connid, 0, 0 ); + "get_ctrls: conn %lu\n", op->o_connid, 0, 0 ); #else Debug( LDAP_DEBUG_TRACE, "=> get_ctrls\n", 0, 0, 0 ); #endif if( op->o_protocol < LDAP_VERSION3 ) { - rc = SLAPD_DISCONNECT; - errmsg = "controls require LDAPv3"; + rs->sr_err = SLAPD_DISCONNECT; + rs->sr_text = "controls require LDAPv3"; goto return_results; } /* one for first control, one for termination */ - op->o_ctrls = ch_malloc( 2 * sizeof(LDAPControl *) ); + op->o_ctrls = op->o_tmpalloc( 2 * sizeof(LDAPControl *), op->o_tmpmemctx ); #if 0 if( op->ctrls == NULL ) { - rc = LDAP_NO_MEMORY; - errmsg = "no memory"; + rs->sr_err = LDAP_NO_MEMORY; + rs->sr_text = "no memory"; goto return_results; } #endif @@ -394,24 +412,14 @@ int get_ctrls( LDAPControl *c; LDAPControl **tctrls; - c = ch_calloc( 1, sizeof(LDAPControl) ); - -#if 0 - if( c == NULL ) { - ldap_controls_free(op->o_ctrls); - op->o_ctrls = NULL; - - rc = LDAP_NO_MEMORY; - errmsg = "no memory"; - goto return_results; - } -#endif + c = op->o_tmpalloc( sizeof(LDAPControl), op->o_tmpmemctx ); + memset(c, 0, sizeof(LDAPControl)); /* allocate pointer space for current controls (nctrls) * + this control + extra NULL */ - tctrls = ch_realloc( op->o_ctrls, - (nctrls+2) * sizeof(LDAPControl *)); + tctrls = op->o_tmprealloc( op->o_ctrls, + (nctrls+2) * sizeof(LDAPControl *), op->o_tmpmemctx ); #if 0 if( tctrls == NULL ) { @@ -419,8 +427,8 @@ int get_ctrls( ldap_controls_free(op->o_ctrls); op->o_ctrls = NULL; - rc = LDAP_NO_MEMORY; - errmsg = "no memory"; + rs->sr_err = LDAP_NO_MEMORY; + rs->sr_text = "no memory"; goto return_results; } #endif @@ -429,38 +437,39 @@ int get_ctrls( op->o_ctrls[nctrls++] = c; op->o_ctrls[nctrls] = NULL; - tag = ber_scanf( ber, "{a" /*}*/, &c->ldctl_oid ); + tag = ber_scanf( ber, "{m" /*}*/, &bv ); + c->ldctl_oid = bv.bv_val; if( tag == LBER_ERROR ) { #ifdef NEW_LOGGING LDAP_LOG( OPERATION, INFO, "get_ctrls: conn %lu get OID failed.\n", - conn->c_connid, 0, 0 ); + op->o_connid, 0, 0 ); #else Debug( LDAP_DEBUG_TRACE, "=> get_ctrls: get oid failed.\n", 0, 0, 0 ); #endif - ldap_controls_free( op->o_ctrls ); + slap_free_ctrls( op, op->o_ctrls ); op->o_ctrls = NULL; - rc = SLAPD_DISCONNECT; - errmsg = "decoding controls error"; + rs->sr_err = SLAPD_DISCONNECT; + rs->sr_text = "decoding controls error"; goto return_results; } else if( c->ldctl_oid == NULL ) { #ifdef NEW_LOGGING LDAP_LOG( OPERATION, INFO, "get_ctrls: conn %lu got emtpy OID.\n", - conn->c_connid, 0, 0 ); + op->o_connid, 0, 0 ); #else Debug( LDAP_DEBUG_TRACE, "get_ctrls: conn %lu got emtpy OID.\n", - conn->c_connid, 0, 0 ); + op->o_connid, 0, 0 ); #endif - ldap_controls_free( op->o_ctrls ); + slap_free_ctrls( op, op->o_ctrls ); op->o_ctrls = NULL; - rc = LDAP_PROTOCOL_ERROR; - errmsg = "OID field is empty"; + rs->sr_err = LDAP_PROTOCOL_ERROR; + rs->sr_text = "OID field is empty"; goto return_results; } @@ -474,15 +483,15 @@ int get_ctrls( #ifdef NEW_LOGGING LDAP_LOG( OPERATION, INFO, "get_ctrls: conn %lu get crit failed.\n", - conn->c_connid, 0, 0 ); + op->o_connid, 0, 0 ); #else Debug( LDAP_DEBUG_TRACE, "=> get_ctrls: get crit failed.\n", 0, 0, 0 ); #endif - ldap_controls_free( op->o_ctrls ); + slap_free_ctrls( op, op->o_ctrls ); op->o_ctrls = NULL; - rc = SLAPD_DISCONNECT; - errmsg = "decoding controls error"; + rs->sr_err = SLAPD_DISCONNECT; + rs->sr_text = "decoding controls error"; goto return_results; } @@ -491,24 +500,24 @@ int get_ctrls( } if( tag == LBER_OCTETSTRING ) { - tag = ber_scanf( ber, "o", &c->ldctl_value ); + tag = ber_scanf( ber, "m", &c->ldctl_value ); if( tag == LBER_ERROR ) { #ifdef NEW_LOGGING LDAP_LOG( OPERATION, INFO, "get_ctrls: conn %lu: " "%s (%scritical): get value failed.\n", - conn->c_connid, c->ldctl_oid, + op->o_connid, c->ldctl_oid, c->ldctl_iscritical ? "" : "non" ); #else Debug( LDAP_DEBUG_TRACE, "=> get_ctrls: conn %lu: " "%s (%scritical): get value failed.\n", - conn->c_connid, c->ldctl_oid, + op->o_connid, c->ldctl_oid, c->ldctl_iscritical ? "" : "non" ); #endif - ldap_controls_free( op->o_ctrls ); + slap_free_ctrls( op, op->o_ctrls ); op->o_ctrls = NULL; - rc = SLAPD_DISCONNECT; - errmsg = "decoding controls error"; + rs->sr_err = SLAPD_DISCONNECT; + rs->sr_text = "decoding controls error"; goto return_results; } } @@ -516,7 +525,7 @@ int get_ctrls( #ifdef NEW_LOGGING LDAP_LOG( OPERATION, INFO, "get_ctrls: conn %lu oid=\"%s\" (%scritical)\n", - conn->c_connid, c->ldctl_oid, c->ldctl_iscritical ? "" : "non" ); + op->o_connid, c->ldctl_oid, c->ldctl_iscritical ? "" : "non" ); #else Debug( LDAP_DEBUG_TRACE, "=> get_ctrls: oid=\"%s\" (%scritical)\n", @@ -557,11 +566,11 @@ int get_ctrls( break; case LDAP_REQ_EXTENDED: tagmask=~0L; - assert( op->o_extendedop != NULL ); + assert( op->ore_reqoid.bv_val != NULL ); if( sc->sc_extendedops != NULL ) { int i; for( i=0; sc->sc_extendedops[i] != NULL; i++ ) { - if( strcmp( op->o_extendedop, sc->sc_extendedops[i] ) + if( strcmp( op->ore_reqoid.bv_val, sc->sc_extendedops[i] ) == 0 ) { tagmask=0L; @@ -571,8 +580,8 @@ int get_ctrls( } break; default: - rc = LDAP_OTHER; - errmsg = "controls internal error"; + rs->sr_err = LDAP_OTHER; + rs->sr_text = "controls internal error"; goto return_results; } @@ -580,14 +589,14 @@ int get_ctrls( /* available extension */ if( !sc->sc_parse ) { - rc = LDAP_OTHER; - errmsg = "not yet implemented"; + rs->sr_err = LDAP_OTHER; + rs->sr_text = "not yet implemented"; goto return_results; } - rc = sc->sc_parse( conn, op, c, &errmsg ); + rs->sr_err = sc->sc_parse( op, rs, c ); - if( rc != LDAP_SUCCESS ) goto return_results; + if( rs->sr_err != LDAP_SUCCESS ) goto return_results; if ( sc->sc_mask & SLAP_CTRL_FRONTEND ) { /* kludge to disable backend_control() check */ @@ -602,15 +611,15 @@ int get_ctrls( } else if( c->ldctl_iscritical ) { /* unavailable CRITICAL control */ - rc = LDAP_UNAVAILABLE_CRITICAL_EXTENSION; - errmsg = "critical extension is unavailable"; + rs->sr_err = LDAP_UNAVAILABLE_CRITICAL_EXTENSION; + rs->sr_text = "critical extension is unavailable"; goto return_results; } } else if( c->ldctl_iscritical ) { /* unrecognized CRITICAL control */ - rc = LDAP_UNAVAILABLE_CRITICAL_EXTENSION; - errmsg = "critical extension is not recognized"; + rs->sr_err = LDAP_UNAVAILABLE_CRITICAL_EXTENSION; + rs->sr_text = "critical extension is not recognized"; goto return_results; } } @@ -619,38 +628,64 @@ return_results: #ifdef NEW_LOGGING LDAP_LOG( OPERATION, RESULTS, "get_ctrls: n=%d rc=%d err=\"%s\"\n", - nctrls, rc, errmsg ? errmsg : "" ); + nctrls, rs->sr_err, rs->sr_text ? rs->sr_text : "" ); #else Debug( LDAP_DEBUG_TRACE, "<= get_ctrls: n=%d rc=%d err=\"%s\"\n", - nctrls, rc, errmsg ? errmsg : ""); + nctrls, rs->sr_err, rs->sr_text ? rs->sr_text : ""); #endif - if( sendres && rc != LDAP_SUCCESS ) { - if( rc == SLAPD_DISCONNECT ) { - send_ldap_disconnect( conn, op, LDAP_PROTOCOL_ERROR, errmsg ); + if( sendres && 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( conn, op, rc, - NULL, errmsg, NULL, NULL ); + send_ldap_result( op, rs ); } } - return rc; + return rs->sr_err; +} + +static int parseModifyIncrement ( + Operation *op, + SlapReply *rs, + LDAPControl *ctrl ) +{ +#if 0 + if ( op->o_parseModifyIncrement != SLAP_NO_CONTROL ) { + rs->sr_text = "modifyIncrement control specified multiple times"; + return LDAP_PROTOCOL_ERROR; + } +#endif + + if ( ctrl->ldctl_value.bv_len ) { + rs->sr_text = "modifyIncrement control value not empty"; + return LDAP_PROTOCOL_ERROR; + } + +#if 0 + op->o_parseModifyIncrement = ctrl->ldctl_iscritical + ? SLAP_CRITICAL_CONTROL + : SLAP_NONCRITICAL_CONTROL; +#endif + + return LDAP_SUCCESS; } static int parseManageDSAit ( - Connection *conn, Operation *op, - LDAPControl *ctrl, - const char **text ) + SlapReply *rs, + LDAPControl *ctrl ) { if ( op->o_managedsait != SLAP_NO_CONTROL ) { - *text = "manageDSAit control specified multiple times"; + rs->sr_text = "manageDSAit control specified multiple times"; return LDAP_PROTOCOL_ERROR; } if ( ctrl->ldctl_value.bv_len ) { - *text = "manageDSAit control value not empty"; + rs->sr_text = "manageDSAit control value not empty"; return LDAP_PROTOCOL_ERROR; } @@ -662,16 +697,15 @@ static int parseManageDSAit ( } static int parseProxyAuthz ( - Connection *conn, Operation *op, - LDAPControl *ctrl, - const char **text ) + SlapReply *rs, + LDAPControl *ctrl ) { - int rc; - struct berval dn = { 0, NULL }; + int rc; + struct berval dn = { 0, NULL }; if ( op->o_proxy_authz != SLAP_NO_CONTROL ) { - *text = "proxy authorization control specified multiple times"; + rs->sr_text = "proxy authorization control specified multiple times"; return LDAP_PROTOCOL_ERROR; } @@ -682,13 +716,13 @@ static int parseProxyAuthz ( #ifdef NEW_LOGGING LDAP_LOG( OPERATION, ARGS, "parseProxyAuthz: conn %lu authzid=\"%s\"\n", - conn->c_connid, + op->o_connid, ctrl->ldctl_value.bv_len ? ctrl->ldctl_value.bv_val : "anonymous", 0 ); #else Debug( LDAP_DEBUG_ARGS, "parseProxyAuthz: conn %lu authzid=\"%s\"\n", - conn->c_connid, + op->o_connid, ctrl->ldctl_value.bv_len ? ctrl->ldctl_value.bv_val : "anonymous", 0 ); #endif @@ -697,11 +731,11 @@ static int parseProxyAuthz ( #ifdef NEW_LOGGING LDAP_LOG( OPERATION, RESULTS, "parseProxyAuthz: conn=%lu anonymous\n", - conn->c_connid, 0, 0 ); + op->o_connid, 0, 0 ); #else Debug( LDAP_DEBUG_TRACE, "parseProxyAuthz: conn=%lu anonymous\n", - conn->c_connid, 0, 0 ); + op->o_connid, 0, 0 ); #endif /* anonymous */ @@ -716,35 +750,36 @@ static int parseProxyAuthz ( return LDAP_SUCCESS; } - rc = slap_sasl_getdn( conn, - ctrl->ldctl_value.bv_val, ctrl->ldctl_value.bv_len, - NULL, &dn, SLAP_GETDN_AUTHZID ); + rc = slap_sasl_getdn( op->o_conn, op, + ctrl->ldctl_value.bv_val, ctrl->ldctl_value.bv_len, + NULL, &dn, SLAP_GETDN_AUTHZID ); if( rc != LDAP_SUCCESS || !dn.bv_len ) { if ( dn.bv_val ) { ch_free( dn.bv_val ); } - *text = "authzId mapping failed"; + rs->sr_text = "authzId mapping failed"; return LDAP_PROXY_AUTHZ_FAILURE; + } #ifdef NEW_LOGGING LDAP_LOG( OPERATION, RESULTS, "parseProxyAuthz: conn=%lu \"%s\"\n", - conn->c_connid, + op->o_connid, dn.bv_len ? dn.bv_val : "(NULL)", 0 ); #else Debug( LDAP_DEBUG_TRACE, "parseProxyAuthz: conn=%lu \"%s\"\n", - conn->c_connid, + op->o_connid, dn.bv_len ? dn.bv_val : "(NULL)", 0 ); #endif - rc = slap_sasl_authorized( conn, &op->o_ndn, &dn ); + rc = slap_sasl_authorized( op, &op->o_ndn, &dn ); if( rc ) { ch_free( dn.bv_val ); - *text = "not authorized to assume identity"; + rs->sr_text = "not authorized to assume identity"; return LDAP_PROXY_AUTHZ_FAILURE; } @@ -764,18 +799,17 @@ static int parseProxyAuthz ( } static int parseNoOp ( - Connection *conn, Operation *op, - LDAPControl *ctrl, - const char **text ) + SlapReply *rs, + LDAPControl *ctrl ) { if ( op->o_noop != SLAP_NO_CONTROL ) { - *text = "noop control specified multiple times"; + rs->sr_text = "noop control specified multiple times"; return LDAP_PROTOCOL_ERROR; } if ( ctrl->ldctl_value.bv_len ) { - *text = "noop control value not empty"; + rs->sr_text = "noop control value not empty"; return LDAP_PROTOCOL_ERROR; } @@ -786,12 +820,10 @@ static int parseNoOp ( return LDAP_SUCCESS; } -#ifdef LDAP_CONTROL_PAGEDRESULTS static int parsePagedResults ( - Connection *conn, Operation *op, - LDAPControl *ctrl, - const char **text ) + SlapReply *rs, + LDAPControl *ctrl ) { ber_tag_t tag; ber_int_t size; @@ -799,12 +831,12 @@ static int parsePagedResults ( struct berval cookie = { 0, NULL }; if ( op->o_pagedresults != SLAP_NO_CONTROL ) { - *text = "paged results control specified multiple times"; + rs->sr_text = "paged results control specified multiple times"; return LDAP_PROTOCOL_ERROR; } if ( ctrl->ldctl_value.bv_len == 0 ) { - *text = "paged results control value is empty (or absent)"; + rs->sr_text = "paged results control value is empty (or absent)"; return LDAP_PROTOCOL_ERROR; } @@ -818,7 +850,7 @@ static int parsePagedResults ( */ ber = ber_init( &ctrl->ldctl_value ); if( ber == NULL ) { - *text = "internal error"; + rs->sr_text = "internal error"; return LDAP_OTHER; } @@ -826,12 +858,12 @@ static int parsePagedResults ( (void) ber_free( ber, 1 ); if( tag == LBER_ERROR ) { - *text = "paged results control could not be decoded"; + rs->sr_text = "paged results control could not be decoded"; return LDAP_PROTOCOL_ERROR; } if( size < 0 ) { - *text = "paged results control size invalid"; + rs->sr_text = "paged results control size invalid"; return LDAP_PROTOCOL_ERROR; } @@ -839,7 +871,7 @@ static int parsePagedResults ( PagedResultsCookie reqcookie; if( cookie.bv_len != sizeof( reqcookie ) ) { /* bad cookie */ - *text = "paged results cookie is invalid"; + rs->sr_text = "paged results cookie is invalid"; return LDAP_PROTOCOL_ERROR; } @@ -847,11 +879,11 @@ static int parsePagedResults ( if( reqcookie > op->o_pagedresults_state.ps_cookie ) { /* bad cookie */ - *text = "paged results cookie is invalid"; + rs->sr_text = "paged results cookie is invalid"; return LDAP_PROTOCOL_ERROR; } else if( reqcookie < op->o_pagedresults_state.ps_cookie ) { - *text = "paged results cookie is invalid or old"; + rs->sr_text = "paged results cookie is invalid or old"; return LDAP_UNWILLING_TO_PERFORM; } } else { @@ -868,275 +900,314 @@ static int parsePagedResults ( return LDAP_SUCCESS; } -#endif -int parseValuesReturnFilter ( - Connection *conn, +static int parseAssert ( Operation *op, - LDAPControl *ctrl, - const char **text ) + SlapReply *rs, + LDAPControl *ctrl ) { - int rc; BerElement *ber; struct berval fstr = { 0, NULL }; const char *err_msg = ""; - if ( op->o_valuesreturnfilter != SLAP_NO_CONTROL ) { - *text = "valuesReturnFilter control specified multiple times"; + if ( op->o_assert != SLAP_NO_CONTROL ) { + rs->sr_text = "assert control specified multiple times"; return LDAP_PROTOCOL_ERROR; } if ( ctrl->ldctl_value.bv_len == 0 ) { - *text = "valuesReturnFilter control value is empty (or absent)"; + rs->sr_text = "assert control value is empty (or absent)"; return LDAP_PROTOCOL_ERROR; } ber = ber_init( &(ctrl->ldctl_value) ); if (ber == NULL) { - *text = "internal error"; + rs->sr_text = "assert control: internal error"; return LDAP_OTHER; } - rc = get_vrFilter( conn, ber, &(op->vrFilter), &err_msg); + rs->sr_err = get_filter( op, ber, &(op->o_assertion), &rs->sr_text); - if( rc != LDAP_SUCCESS ) { - text = &err_msg; - if( rc == SLAPD_DISCONNECT ) { - send_ldap_disconnect( conn, op, - LDAP_PROTOCOL_ERROR, *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( conn, op, rc, - NULL, *text, NULL, NULL ); + send_ldap_result( op, rs ); } - if( fstr.bv_val != NULL) free( fstr.bv_val ); - if( op->vrFilter != NULL) vrFilter_free( op->vrFilter ); - - } else { - vrFilter2bv( op->vrFilter, &fstr ); + if( op->o_assertion != NULL ) { + filter_free_x( op, op->o_assertion ); + } + return rs->sr_err; } +#ifdef LDAP_DEBUG + filter2bv_x( op, op->o_assertion, &fstr ); + #ifdef NEW_LOGGING LDAP_LOG( OPERATION, ARGS, - "parseValuesReturnFilter: conn %d vrFilter: %s\n", - conn->c_connid, fstr.bv_len ? fstr.bv_val : "empty" , 0 ); + "parseAssert: conn %ld assert: %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 ); + 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_valuesreturnfilter = ctrl->ldctl_iscritical + op->o_assert = ctrl->ldctl_iscritical ? SLAP_CRITICAL_CONTROL : SLAP_NONCRITICAL_CONTROL; + rs->sr_err = LDAP_SUCCESS; return LDAP_SUCCESS; } -#ifdef LDAP_CONTROL_SUBENTRIES -static int parseSubentries ( - Connection *conn, +static int parsePreRead ( Operation *op, - LDAPControl *ctrl, - const char **text ) + SlapReply *rs, + LDAPControl *ctrl ) { - if ( op->o_subentries != SLAP_NO_CONTROL ) { - *text = "subentries control specified multiple times"; + 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; } - /* 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 )) - { - *text = "subentries control value encoding is bogus"; + if ( ctrl->ldctl_value.bv_len == 0 ) { + rs->sr_text = "preread control value is empty (or absent)"; return LDAP_PROTOCOL_ERROR; } - op->o_subentries = ctrl->ldctl_iscritical + 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; ildctl_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_subentries_visibility = (ctrl->ldctl_value.bv_val[2] != 0x00); + op->o_preread_attrs = an; + rs->sr_err = LDAP_SUCCESS; return LDAP_SUCCESS; } -#endif -#ifdef LDAP_CONTROL_X_PERMISSIVE_MODIFY -static int parsePermissiveModify ( - Connection *conn, +static int parsePostRead ( Operation *op, - LDAPControl *ctrl, - const char **text ) + SlapReply *rs, + LDAPControl *ctrl ) { - if ( op->o_permissive_modify != SLAP_NO_CONTROL ) { - *text = "permissiveModify control specified multiple times"; + 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 ) { - *text = "permissiveModify control value not empty"; + if ( ctrl->ldctl_value.bv_len == 0 ) { + rs->sr_text = "postread control value is empty (or absent)"; return LDAP_PROTOCOL_ERROR; } - op->o_permissive_modify = ctrl->ldctl_iscritical - ? SLAP_CRITICAL_CONTROL - : SLAP_NONCRITICAL_CONTROL; - - return LDAP_SUCCESS; -} -#endif + ber = ber_init( &(ctrl->ldctl_value) ); + if (ber == NULL) { + rs->sr_text = "postread control: internal error"; + return LDAP_OTHER; + } -#ifdef LDAP_CONTROL_X_DOMAIN_SCOPE -static int parseDomainScope ( - Connection *conn, - Operation *op, - LDAPControl *ctrl, - const char **text ) -{ - if ( op->o_domain_scope != SLAP_NO_CONTROL ) { - *text = "domainScope control specified multiple times"; + 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; } - if ( ctrl->ldctl_value.bv_len ) { - *text = "domainScope control value not empty"; - return LDAP_PROTOCOL_ERROR; + for( i=0; ildctl_iscritical ) { + rs->sr_text = dummy ? dummy : "postread control: unknown attributeType"; + return rc; + } } - op->o_domain_scope = ctrl->ldctl_iscritical + 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; } -#endif -#ifdef LDAP_CLIENT_UPDATE -static int parseClientUpdate ( - Connection *conn, +int parseValuesReturnFilter ( Operation *op, - LDAPControl *ctrl, - const char **text ) + SlapReply *rs, + LDAPControl *ctrl ) { - ber_tag_t tag; - BerElement *ber; - ber_int_t type; - ber_int_t interval; - ber_len_t len; - struct berval scheme = { 0, NULL }; - struct berval cookie = { 0, NULL }; - - if ( op->o_clientupdate != SLAP_NO_CONTROL ) { - *text = "LCUP client update control specified multiple times"; - return LDAP_PROTOCOL_ERROR; - } + BerElement *ber; + struct berval fstr = { 0, NULL }; + const char *err_msg = ""; -#ifdef LDAP_SYNC - if ( op->o_sync != SLAP_NO_CONTROL ) { - *text = "LDAP Client Update and Sync controls used together"; + if ( op->o_valuesreturnfilter != SLAP_NO_CONTROL ) { + rs->sr_text = "valuesReturnFilter control specified multiple times"; return LDAP_PROTOCOL_ERROR; } -#endif if ( ctrl->ldctl_value.bv_len == 0 ) { - *text = "LCUP client update control value is empty (or absent)"; + rs->sr_text = "valuesReturnFilter control value is empty (or absent)"; return LDAP_PROTOCOL_ERROR; } - /* Parse the control value - * ClientUpdateControlValue ::= SEQUENCE { - * updateType ENUMERATED { - * synchronizeOnly {0}, - * synchronizeAndPersist {1}, - * persistOnly {2} }, - * sendCookieInterval INTEGER OPTIONAL, - * cookie LCUPCookie OPTIONAL - * } - */ - - ber = ber_init( &ctrl->ldctl_value ); - if( ber == NULL ) { - *text = "internal 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 ( (tag = ber_scanf( ber, "{i" /*}*/, &type )) == LBER_ERROR ) { - *text = "LCUP client update control : decoding error"; - return LDAP_PROTOCOL_ERROR; + 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 ); } - switch( type ) { - case LDAP_CUP_SYNC_ONLY: - type = SLAP_LCUP_SYNC; - break; - case LDAP_CUP_SYNC_AND_PERSIST: - type = SLAP_LCUP_SYNC_AND_PERSIST; - break; - case LDAP_CUP_PERSIST_ONLY: - type = SLAP_LCUP_PERSIST; - break; - default: - *text = "LCUP client update control : unknown update type"; +#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; } - if ( (tag = ber_peek_tag( ber, &len )) == LBER_DEFAULT ) { - *text = "LCUP client update control : decoding 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; } - if ( tag == LDAP_CUP_TAG_INTERVAL ) { - if ( (tag = ber_scanf( ber, "i", &interval )) == LBER_ERROR ) { - *text = "LCUP client update control : decoding error"; - return LDAP_PROTOCOL_ERROR; - } - - if ( interval <= 0 ) { - /* server chooses interval */ - interval = LDAP_CUP_DEFAULT_SEND_COOKIE_INTERVAL; - } + op->o_subentries = ctrl->ldctl_iscritical + ? SLAP_CRITICAL_CONTROL + : SLAP_NONCRITICAL_CONTROL; - } else { - /* server chooses interval */ - interval = LDAP_CUP_DEFAULT_SEND_COOKIE_INTERVAL; - } + op->o_subentries_visibility = (ctrl->ldctl_value.bv_val[2] != 0x00); + + return LDAP_SUCCESS; +} +#endif - if ( (tag = ber_peek_tag( ber, &len )) == LBER_DEFAULT ) { - *text = "LCUP client update control : decoding error"; +#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 ( tag == LDAP_CUP_TAG_COOKIE ) { - if ( (tag = ber_scanf( ber, /*{*/ "{mm}}", - &scheme, &cookie )) == LBER_ERROR ) - { - *text = "LCUP client update control : decoding error"; - return LDAP_PROTOCOL_ERROR; - } + if ( ctrl->ldctl_value.bv_len ) { + rs->sr_text = "permissiveModify control value not empty"; + return LDAP_PROTOCOL_ERROR; } - /* TODO : Cookie Scheme Validation */ -#if 0 - if ( lcup_cookie_scheme_validate(scheme) != LDAP_SUCCESS ) { - *text = "Unsupported LCUP cookie scheme"; - return LCUP_UNSUPPORTED_SCHEME; - } + op->o_permissive_modify = ctrl->ldctl_iscritical + ? SLAP_CRITICAL_CONTROL + : SLAP_NONCRITICAL_CONTROL; - if ( lcup_cookie_validate(scheme, cookie) != LDAP_SUCCESS ) { - *text = "Invalid LCUP cookie"; - return LCUP_INVALID_COOKIE; - } + return LDAP_SUCCESS; +} #endif - ber_dupbv( &op->o_clientupdate_state, &cookie ); - - (void) ber_free( ber, 1 ); +#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; + } - op->o_clientupdate_type = (char) type; - op->o_clientupdate_interval = interval; + if ( ctrl->ldctl_value.bv_len ) { + rs->sr_text = "domainScope control value not empty"; + return LDAP_PROTOCOL_ERROR; + } - op->o_clientupdate = ctrl->ldctl_iscritical + op->o_domain_scope = ctrl->ldctl_iscritical ? SLAP_CRITICAL_CONTROL : SLAP_NONCRITICAL_CONTROL; @@ -1144,33 +1215,24 @@ static int parseClientUpdate ( } #endif -#ifdef LDAP_SYNC -static int parseLdupSync ( - Connection *conn, +static int parseLDAPsync ( Operation *op, - LDAPControl *ctrl, - const char **text ) + SlapReply *rs, + LDAPControl *ctrl ) { ber_tag_t tag; BerElement *ber; ber_int_t mode; ber_len_t len; - struct berval cookie = { 0, NULL }; + struct slap_session_entry *se; if ( op->o_sync != SLAP_NO_CONTROL ) { - *text = "LDAP Sync control specified multiple times"; - return LDAP_PROTOCOL_ERROR; - } - -#ifdef LDAP_CLIENT_UPDATE - if ( op->o_clientupdate != SLAP_NO_CONTROL ) { - *text = "LDAP Sync and LDAP Client Update controls used together"; + rs->sr_text = "LDAP Sync control specified multiple times"; return LDAP_PROTOCOL_ERROR; } -#endif if ( ctrl->ldctl_value.bv_len == 0 ) { - *text = "LDAP Sync control value is empty (or absent)"; + rs->sr_text = "LDAP Sync control value is empty (or absent)"; return LDAP_PROTOCOL_ERROR; } @@ -1188,12 +1250,12 @@ static int parseLdupSync ( ber = ber_init( &ctrl->ldctl_value ); if( ber == NULL ) { - *text = "internal error"; + rs->sr_text = "internal error"; return LDAP_OTHER; } if ( (tag = ber_scanf( ber, "{i" /*}*/, &mode )) == LBER_ERROR ) { - *text = "LDAP Sync control : mode decoding error"; + rs->sr_text = "LDAP Sync control : mode decoding error"; return LDAP_PROTOCOL_ERROR; } @@ -1205,42 +1267,32 @@ static int parseLdupSync ( mode = SLAP_SYNC_REFRESH_AND_PERSIST; break; default: - *text = "LDAP Sync control : unknown update mode"; + rs->sr_text = "LDAP Sync control : unknown update mode"; return LDAP_PROTOCOL_ERROR; } tag = ber_peek_tag( ber, &len ); - if ( tag == LDAP_SYNC_TAG_COOKIE ) { - if (( ber_scanf( ber, /*{*/ "m}", - &cookie )) == LBER_ERROR ) { - *text = "LDAP Sync control : cookie decoding error"; + 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; } - } else { - if (( ber_scanf( ber, /*{*/ "}")) == LBER_ERROR ) { - *text = "LDAP Sync control : decoding 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; } - cookie.bv_len = 0; - cookie.bv_val = NULL; } - - /* TODO : Cookie Scheme Validation */ -#if 0 - if ( lcup_cookie_scheme_validate(scheme) != LDAP_SUCCESS ) { - *text = "Unsupported LCUP cookie scheme"; - return LCUP_UNSUPPORTED_SCHEME; + if (( ber_scanf( ber, /*{*/ "}")) == LBER_ERROR ) { + rs->sr_text = "LDAP Sync control : decoding error"; + return LDAP_PROTOCOL_ERROR; } - if ( lcup_cookie_validate(scheme, cookie) != LDAP_SUCCESS ) { - *text = "Invalid LCUP cookie"; - return LCUP_INVALID_COOKIE; - } -#endif - - ber_dupbv( &op->o_sync_state, &cookie ); - (void) ber_free( ber, 1 ); op->o_sync_mode = (char) mode; @@ -1251,4 +1303,3 @@ static int parseLdupSync ( return LDAP_SUCCESS; } -#endif