X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=servers%2Fslapd%2Fcontrols.c;h=53d927004f8f109bfcb9142fb8d165a479ec0351;hb=c5b6a86502dc0c16027cd87e3d9544e9078083db;hp=f0338dc97455b84a37232bdd338249ac73077daf;hpb=d2f5d75885a7c3a23cf846da6b4448f869a58a5b;p=openldap diff --git a/servers/slapd/controls.c b/servers/slapd/controls.c index f0338dc974..53d927004f 100644 --- a/servers/slapd/controls.c +++ b/servers/slapd/controls.c @@ -19,15 +19,18 @@ #include "../../libraries/liblber/lber-int.h" -#define SLAP_CTRL_ABANDON 0x0001 -#define SLAP_CTRL_ADD 0x2002 -#define SLAP_CTRL_BIND 0x0004 -#define SLAP_CTRL_COMPARE 0x1008 -#define SLAP_CTRL_DELETE 0x2010 -#define SLAP_CTRL_MODIFY 0x2020 -#define SLAP_CTRL_RENAME 0x2040 -#define SLAP_CTRL_SEARCH 0x1080 -#define SLAP_CTRL_UNBIND 0x0100 +#define SLAP_CTRL_FRONTEND 0x80000000U + +#define SLAP_CTRL_OPFLAGS 0x0000FFFFU +#define SLAP_CTRL_ABANDON 0x00000001U +#define SLAP_CTRL_ADD 0x00002002U +#define SLAP_CTRL_BIND 0x00000004U +#define SLAP_CTRL_COMPARE 0x00001008U +#define SLAP_CTRL_DELETE 0x00002010U +#define SLAP_CTRL_MODIFY 0x00002020U +#define SLAP_CTRL_RENAME 0x00002040U +#define SLAP_CTRL_SEARCH 0x00001080U +#define SLAP_CTRL_UNBIND 0x00000100U #define SLAP_CTRL_INTROGATE (SLAP_CTRL_COMPARE|SLAP_CTRL_SEARCH) #define SLAP_CTRL_UPDATE \ @@ -42,10 +45,15 @@ typedef int (SLAP_CTRL_PARSE_FN) LDAP_P(( static SLAP_CTRL_PARSE_FN parseManageDSAit; static SLAP_CTRL_PARSE_FN parseSubentries; +static SLAP_CTRL_PARSE_FN parseNoOp; +static SLAP_CTRL_PARSE_FN parsePagedResults; +static SLAP_CTRL_PARSE_FN parseValuesReturnFilter; + +#undef sc_mask /* avoid conflict with Irix 6.5 */ static struct slap_control { char *sc_oid; - int sc_ops_mask; + slap_mask_t sc_mask; char **sc_extendedops; SLAP_CTRL_PARSE_FN *sc_parse; @@ -53,9 +61,26 @@ static struct slap_control { { LDAP_CONTROL_MANAGEDSAIT, SLAP_CTRL_ACCESS, NULL, parseManageDSAit }, +#ifdef LDAP_CONTROL_SUBENTRIES { LDAP_CONTROL_SUBENTRIES, SLAP_CTRL_SEARCH, NULL, parseSubentries }, +#endif +#ifdef LDAP_CONTROL_NOOP + { LDAP_CONTROL_NOOP, + SLAP_CTRL_UPDATE, NULL, + parseNoOp }, +#endif +#ifdef LDAP_CONTROL_PAGEDRESULTS_REQUEST + { LDAP_CONTROL_PAGEDRESULTS_REQUEST, + SLAP_CTRL_SEARCH, NULL, + parsePagedResults }, +#endif +#ifdef LDAP_CONTROL_VALUESRETURNFILTER + { LDAP_CONTROL_VALUESRETURNFILTER, + SLAP_CTRL_SEARCH, NULL, + parseValuesReturnFilter }, +#endif { NULL } }; @@ -87,8 +112,7 @@ int get_ctrls( ber_len_t len; char *opaque; BerElement *ber = op->o_ber; - LDAPControl ***ctrls = &op->o_ctrls; - struct slap_control *c; + struct slap_control *sc; int rc = LDAP_SUCCESS; const char *errmsg = NULL; @@ -110,8 +134,7 @@ int get_ctrls( } #ifdef NEW_LOGGING - LDAP_LOG(( "operation", LDAP_LEVEL_ENTRY, - "get_ctrls: conn %d\n", conn->c_connid )); + LDAP_LOG( OPERATION, ENTRY, "get_ctrls: conn %lu\n", conn->c_connid, 0, 0 ); #else Debug( LDAP_DEBUG_TRACE, "=> get_ctrls\n", 0, 0, 0 ); #endif @@ -121,69 +144,74 @@ int get_ctrls( goto return_results; } - /* set through each element */ - *ctrls = ch_malloc( 1 * sizeof(LDAPControl *) ); + /* one for first control, one for termination */ + op->o_ctrls = ch_malloc( 2 * sizeof(LDAPControl *) ); #if 0 - if( *ctrls == NULL ) { + if( op->ctrls == NULL ) { rc = LDAP_NO_MEMORY; errmsg = "no memory"; goto return_results; } #endif - *ctrls[nctrls] = NULL; + op->o_ctrls[nctrls] = NULL; + /* step through each element */ for( tag = ber_first_element( ber, &len, &opaque ); tag != LBER_ERROR; tag = ber_next_element( ber, &len, opaque ) ) { - LDAPControl *tctrl; + LDAPControl *c; LDAPControl **tctrls; - tctrl = ch_calloc( 1, sizeof(LDAPControl) ); - tctrl->ldctl_oid = NULL; - tctrl->ldctl_value.bv_val = NULL; + 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 /* allocate pointer space for current controls (nctrls) * + this control + extra NULL */ - tctrls = (tctrl == NULL) ? NULL : - ch_realloc(*ctrls, (nctrls+2) * sizeof(LDAPControl *)); + tctrls = ch_realloc( op->o_ctrls, + (nctrls+2) * sizeof(LDAPControl *)); #if 0 if( tctrls == NULL ) { - /* one of the above allocation failed */ - - if( tctrl != NULL ) { - ch_free( tctrl ); - } - - ldap_controls_free(*ctrls); - *ctrls = NULL; + ch_free( c ); + ldap_controls_free(op->o_ctrls); + op->o_ctrls = NULL; rc = LDAP_NO_MEMORY; errmsg = "no memory"; goto return_results; } #endif + op->o_ctrls = tctrls; - tctrls[nctrls++] = tctrl; - tctrls[nctrls] = NULL; + op->o_ctrls[nctrls++] = c; + op->o_ctrls[nctrls] = NULL; - tag = ber_scanf( ber, "{a" /*}*/, &tctrl->ldctl_oid ); + tag = ber_scanf( ber, "{a" /*}*/, &c->ldctl_oid ); if( tag == LBER_ERROR ) { #ifdef NEW_LOGGING - LDAP_LOG(( "operation", LDAP_LEVEL_INFO, - "get_ctrls: conn %d get OID failed.\n", - conn->c_connid )); + LDAP_LOG( OPERATION, INFO, "get_ctrls: conn %lu get OID failed.\n", + conn->c_connid, 0, 0 ); #else Debug( LDAP_DEBUG_TRACE, "=> get_ctrls: get oid failed.\n", 0, 0, 0 ); #endif - *ctrls = NULL; - ldap_controls_free( tctrls ); + ldap_controls_free( op->o_ctrls ); + op->o_ctrls = NULL; rc = SLAPD_DISCONNECT; errmsg = "decoding controls error"; goto return_results; @@ -197,58 +225,64 @@ int get_ctrls( if( tag == LBER_ERROR ) { #ifdef NEW_LOGGING - LDAP_LOG(( "operation", LDAP_LEVEL_INFO, - "get_ctrls: conn %d get crit failed.\n", - conn->c_connid )); + LDAP_LOG( OPERATION, INFO, + "get_ctrls: conn %lu get crit failed.\n", + conn->c_connid, 0, 0 ); #else Debug( LDAP_DEBUG_TRACE, "=> get_ctrls: get crit failed.\n", 0, 0, 0 ); #endif - *ctrls = NULL; - ldap_controls_free( tctrls ); + ldap_controls_free( op->o_ctrls ); + op->o_ctrls = NULL; rc = SLAPD_DISCONNECT; errmsg = "decoding controls error"; goto return_results; } - tctrl->ldctl_iscritical = (crit != 0); + c->ldctl_iscritical = (crit != 0); tag = ber_peek_tag( ber, &len ); } -#ifdef NEW_LOGGING - LDAP_LOG(( "operation", LDAP_LEVEL_INFO, - "get_ctrls: conn %d oid=\"%s\" (%scritical)\n", - conn->c_connid, tctrl->ldctl_oid, - tctrl->ldctl_iscritical ? "" : "non" )); -#else - Debug( LDAP_DEBUG_TRACE, "=> get_ctrls: oid=\"%s\" (%scritical)\n", - tctrl->ldctl_oid, - tctrl->ldctl_iscritical ? "" : "non", - 0 ); -#endif if( tag == LBER_OCTETSTRING ) { - tag = ber_scanf( ber, "o", &tctrl->ldctl_value ); + tag = ber_scanf( ber, "o", &c->ldctl_value ); if( tag == LBER_ERROR ) { #ifdef NEW_LOGGING - LDAP_LOG(( "operation", LDAP_LEVEL_INFO, - "get_ctrls: conn %d get value failed.\n", conn->c_connid )); + LDAP_LOG( OPERATION, INFO, "get_ctrls: conn %lu: " + "%s (%scritical): get value failed.\n", + conn->c_connid, c->ldctl_oid ? c->ldctl_oid : "(NULL)", + c->ldctl_iscritical ? "" : "non" ); #else - Debug( LDAP_DEBUG_TRACE, "=> get_ctrls: get value failed.\n", - 0, 0, 0 ); + Debug( LDAP_DEBUG_TRACE, "=> get_ctrls: conn %lu: " + "%s (%scritical): get value failed.\n", + conn->c_connid, + c->ldctl_oid ? c->ldctl_oid : "(NULL)", + c->ldctl_iscritical ? "" : "non" ); #endif - *ctrls = NULL; - ldap_controls_free( tctrls ); + ldap_controls_free( op->o_ctrls ); + op->o_ctrls = NULL; rc = SLAPD_DISCONNECT; errmsg = "decoding controls error"; goto return_results; } } - c = find_ctrl( tctrl->ldctl_oid ); - if( c != NULL ) { - /* recongized control */ - int tagmask = -1; +#ifdef NEW_LOGGING + LDAP_LOG( OPERATION, INFO, + "get_ctrls: conn %lu oid=\"%s\" (%scritical)\n", + conn->c_connid, c->ldctl_oid ? c->ldctl_oid : "(NULL)", + c->ldctl_iscritical ? "" : "non" ); +#else + Debug( LDAP_DEBUG_TRACE, "=> get_ctrls: oid=\"%s\" (%scritical)\n", + c->ldctl_oid ? c->ldctl_oid : "(NULL)", + c->ldctl_iscritical ? "" : "non", + 0 ); +#endif + + sc = find_ctrl( c->ldctl_oid ); + if( sc != NULL ) { + /* recognized control */ + slap_mask_t tagmask; switch( op->o_tag ) { case LDAP_REQ_ADD: tagmask = SLAP_CTRL_ADD; @@ -276,7 +310,7 @@ int get_ctrls( break; case LDAP_REQ_EXTENDED: /* FIXME: check list of extended operations */ - tagmask = -1; + tagmask = ~0U; break; default: rc = LDAP_OTHER; @@ -284,43 +318,45 @@ int get_ctrls( goto return_results; } - if (( c->sc_ops_mask & tagmask ) == tagmask ) { + if (( sc->sc_mask & tagmask ) == tagmask ) { /* available extension */ - if( !c->sc_parse ) { + if( !sc->sc_parse ) { rc = LDAP_OTHER; errmsg = "not yet implemented"; goto return_results; } - rc = c->sc_parse( conn, op, tctrl, &errmsg ); + rc = sc->sc_parse( conn, op, c, &errmsg ); if( rc != LDAP_SUCCESS ) goto return_results; - } else if( tctrl->ldctl_iscritical ) { + if( sc->sc_mask & SLAP_CTRL_FRONTEND ) { + /* kludge to disable backend_control() check */ + c->ldctl_iscritical = 0; + } + + } else if( c->ldctl_iscritical ) { /* unavailable CRITICAL control */ rc = LDAP_UNAVAILABLE_CRITICAL_EXTENSION; errmsg = "critical extension is unavailable"; goto return_results; } - } else if( tctrl->ldctl_iscritical ) { - /* unrecongized CRITICAL control */ + } else if( c->ldctl_iscritical ) { + /* unrecognized CRITICAL control */ rc = LDAP_UNAVAILABLE_CRITICAL_EXTENSION; - errmsg = "critical extension is not recongized"; + errmsg = "critical extension is not recognized"; goto return_results; } - - *ctrls = tctrls; } return_results: #ifdef NEW_LOGGING - LDAP_LOG(( "operation", LDAP_LEVEL_RESULTS, - "get_ctrls: conn %d %d %d %s\n", - conn->c_connid, nctrls, rc, errmsg ? errmsg : "" )); + LDAP_LOG( OPERATION, RESULTS, + "get_ctrls: n=%d rc=%d err=%s\n", nctrls, rc, errmsg ? errmsg : "" ); #else - Debug( LDAP_DEBUG_TRACE, "<= get_ctrls: %d %d %s\n", + Debug( LDAP_DEBUG_TRACE, "<= get_ctrls: n=%d rc=%d err=%s\n", nctrls, rc, errmsg ? errmsg : ""); #endif @@ -359,6 +395,7 @@ static int parseManageDSAit ( return LDAP_SUCCESS; } +#ifdef LDAP_CONTROL_SUBENTRIES static int parseSubentries ( Connection *conn, Operation *op, @@ -387,3 +424,167 @@ static int parseSubentries ( return LDAP_SUCCESS; } +#endif + +#ifdef LDAP_CONTROL_NOOP +static int parseNoOp ( + Connection *conn, + Operation *op, + LDAPControl *ctrl, + const char **text ) +{ + if ( op->o_noop != SLAP_NO_CONTROL ) { + *text = "noop control specified multiple times"; + return LDAP_PROTOCOL_ERROR; + } + + if ( ctrl->ldctl_value.bv_len ) { + *text = "noop control value not empty"; + return LDAP_PROTOCOL_ERROR; + } + + op->o_noop = ctrl->ldctl_iscritical + ? SLAP_CRITICAL_CONTROL + : SLAP_NONCRITICAL_CONTROL; + + return LDAP_SUCCESS; +} +#endif + +#ifdef LDAP_CONTROL_PAGEDRESULTS_REQUEST +static int parsePagedResults ( + Connection *conn, + Operation *op, + LDAPControl *ctrl, + const char **text ) +{ + ber_tag_t tag; + ber_int_t size; + BerElement *ber; + struct berval cookie = { 0, NULL }; + + if ( op->o_pagedresults != SLAP_NO_CONTROL ) { + *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"; + return LDAP_PROTOCOL_ERROR; + } + + /* Parse the control value + * realSearchControlValue ::= SEQUENCE { + * size INTEGER (0..maxInt), + * -- requested page size from client + * -- result set size estimate from server + * cookie OCTET STRING + */ + ber = ber_init( &ctrl->ldctl_value ); + if( ber == NULL ) { + *text = "internal error"; + return LDAP_OTHER; + } + + tag = ber_scanf( ber, "{im}", &size, &cookie ); + (void) ber_free( ber, 1 ); + + if( tag == LBER_ERROR ) { + *text = "paged results control could not be decoded"; + return LDAP_PROTOCOL_ERROR; + } + + if( size <= 0 ) { + *text = "paged results control size invalid"; + return LDAP_PROTOCOL_ERROR; + } + + if( cookie.bv_len ) { + PagedResultsCookie reqcookie; + if( cookie.bv_len != sizeof( reqcookie ) ) { + /* bad cookie */ + *text = "paged results cookie is invalid"; + return LDAP_PROTOCOL_ERROR; + } + + AC_MEMCPY( &reqcookie, cookie.bv_val, sizeof( reqcookie )); + + if( reqcookie > op->o_pagedresults_state.ps_cookie ) { + /* bad cookie */ + *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"; + return LDAP_UNWILLING_TO_PERFORM; + } + } + + op->o_pagedresults_state.ps_cookie = op->o_opid; + op->o_pagedresults_size = size; + + op->o_pagedresults = ctrl->ldctl_iscritical + ? SLAP_CRITICAL_CONTROL + : SLAP_NONCRITICAL_CONTROL; + + return LDAP_SUCCESS; +} +#endif + +#ifdef LDAP_CONTROL_VALUESRETURNFILTER +int parseValuesReturnFilter ( + Connection *conn, + Operation *op, + LDAPControl *ctrl, + const char **text ) +{ + 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"; + return LDAP_PROTOCOL_ERROR; + } + + ber = ber_init( &(ctrl->ldctl_value) ); + if (ber == NULL) { + *text = "internal error"; + return LDAP_OTHER; + } + + rc = get_vrFilter( conn, ber, &(op->vrFilter), &err_msg); + + if( rc != LDAP_SUCCESS ) { + text = &err_msg; + if( rc == SLAPD_DISCONNECT ) { + send_ldap_disconnect( conn, op, + LDAP_PROTOCOL_ERROR, *text ); + } else { + send_ldap_result( conn, op, rc, + NULL, *text, NULL, NULL ); + } + if( fstr.bv_val != NULL) free( fstr.bv_val ); + if( op->vrFilter != NULL) vrFilter_free( op->vrFilter ); + + } else { + vrFilter2bv( op->vrFilter, &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 ); +#else + Debug( LDAP_DEBUG_ARGS, " vrFilter: %s\n", + fstr.bv_len ? fstr.bv_val : "empty", 0, 0 ); +#endif + + op->o_valuesreturnfilter = ctrl->ldctl_iscritical + ? SLAP_CRITICAL_CONTROL + : SLAP_NONCRITICAL_CONTROL; + + return LDAP_SUCCESS; +} +#endif