2 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
4 * Copyright 1998-2018 The OpenLDAP Foundation.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted only as authorized by the OpenLDAP
11 * A copy of this license is available in the file LICENSE in the
12 * top-level directory of the distribution or, alternatively, at
13 * <http://www.OpenLDAP.org/license.html>.
20 #include <ac/string.h>
21 #include <ac/socket.h>
27 #include "../../libraries/liblber/lber-int.h"
29 static SLAP_CTRL_PARSE_FN parseAssert;
30 static SLAP_CTRL_PARSE_FN parseDomainScope;
31 static SLAP_CTRL_PARSE_FN parseDontUseCopy;
32 static SLAP_CTRL_PARSE_FN parseManageDSAit;
33 static SLAP_CTRL_PARSE_FN parseNoOp;
34 static SLAP_CTRL_PARSE_FN parsePagedResults;
35 static SLAP_CTRL_PARSE_FN parsePermissiveModify;
36 static SLAP_CTRL_PARSE_FN parsePreRead, parsePostRead;
37 static SLAP_CTRL_PARSE_FN parseProxyAuthz;
38 static SLAP_CTRL_PARSE_FN parseRelax;
39 static SLAP_CTRL_PARSE_FN parseSearchOptions;
40 #ifdef SLAP_CONTROL_X_SORTEDRESULTS
41 static SLAP_CTRL_PARSE_FN parseSortedResults;
43 static SLAP_CTRL_PARSE_FN parseSubentries;
44 #ifdef SLAP_CONTROL_X_TREE_DELETE
45 static SLAP_CTRL_PARSE_FN parseTreeDelete;
47 static SLAP_CTRL_PARSE_FN parseValuesReturnFilter;
48 #ifdef SLAP_CONTROL_X_SESSION_TRACKING
49 static SLAP_CTRL_PARSE_FN parseSessionTracking;
51 #ifdef SLAP_CONTROL_X_WHATFAILED
52 static SLAP_CTRL_PARSE_FN parseWhatFailed;
54 #ifdef SLAP_CONTROL_X_LAZY_COMMIT
55 static SLAP_CTRL_PARSE_FN parseLazyCommit;
58 #undef sc_mask /* avoid conflict with Irix 6.5 <sys/signal.h> */
60 const struct berval slap_pre_read_bv = BER_BVC(LDAP_CONTROL_PRE_READ);
61 const struct berval slap_post_read_bv = BER_BVC(LDAP_CONTROL_POST_READ);
63 struct slap_control_ids slap_cids;
69 /* The controlID for this control */
72 /* Operations supported by control */
75 /* Extended operations supported by control */
76 char **sc_extendedops; /* input */
77 BerVarray sc_extendedopsbv; /* run-time use */
79 /* Control parsing callback */
80 SLAP_CTRL_PARSE_FN *sc_parse;
82 LDAP_SLIST_ENTRY(slap_control) sc_next;
85 static LDAP_SLIST_HEAD(ControlsList, slap_control) controls_list
86 = LDAP_SLIST_HEAD_INITIALIZER(&controls_list);
89 * all known request control OIDs should be added to this list
92 * NOTE: initialize num_known_controls to 1 so that cid = 0 always
93 * addresses an undefined control; this allows to safely test for
94 * well known controls even if they are not registered, e.g. if
95 * they get moved to modules. An example is sc_LDAPsync, which
96 * is implemented in the syncprov overlay and thus, if configured
97 * as dynamic module, may not be registered. One side effect is that
98 * slap_known_controls[0] == NULL, so it should always be used
100 * FIXME: should we define the "undefined control" oid?
102 char *slap_known_controls[SLAP_MAX_CIDS+1];
103 static int num_known_controls = 1;
105 static char *proxy_authz_extops[] = {
106 LDAP_EXOP_MODIFY_PASSWD,
112 static char *manageDSAit_extops[] = {
117 #ifdef SLAP_CONTROL_X_SESSION_TRACKING
118 static char *session_tracking_extops[] = {
119 LDAP_EXOP_MODIFY_PASSWD,
126 static struct slap_control control_defs[] = {
127 { LDAP_CONTROL_ASSERT,
128 (int)offsetof(struct slap_control_ids, sc_assert),
129 SLAP_CTRL_UPDATE|SLAP_CTRL_COMPARE|SLAP_CTRL_SEARCH,
131 parseAssert, LDAP_SLIST_ENTRY_INITIALIZER(next) },
132 { LDAP_CONTROL_PRE_READ,
133 (int)offsetof(struct slap_control_ids, sc_preRead),
134 SLAP_CTRL_DELETE|SLAP_CTRL_MODIFY|SLAP_CTRL_RENAME,
136 parsePreRead, LDAP_SLIST_ENTRY_INITIALIZER(next) },
137 { LDAP_CONTROL_POST_READ,
138 (int)offsetof(struct slap_control_ids, sc_postRead),
139 SLAP_CTRL_ADD|SLAP_CTRL_MODIFY|SLAP_CTRL_RENAME,
141 parsePostRead, LDAP_SLIST_ENTRY_INITIALIZER(next) },
142 { LDAP_CONTROL_VALUESRETURNFILTER,
143 (int)offsetof(struct slap_control_ids, sc_valuesReturnFilter),
144 SLAP_CTRL_GLOBAL|SLAP_CTRL_SEARCH,
146 parseValuesReturnFilter, LDAP_SLIST_ENTRY_INITIALIZER(next) },
147 { LDAP_CONTROL_PAGEDRESULTS,
148 (int)offsetof(struct slap_control_ids, sc_pagedResults),
151 parsePagedResults, LDAP_SLIST_ENTRY_INITIALIZER(next) },
152 #ifdef SLAP_CONTROL_X_SORTEDRESULTS
153 { LDAP_CONTROL_SORTREQUEST,
154 (int)offsetof(struct slap_control_ids, sc_sortedResults),
155 SLAP_CTRL_GLOBAL|SLAP_CTRL_SEARCH|SLAP_CTRL_HIDE,
157 parseSortedResults, LDAP_SLIST_ENTRY_INITIALIZER(next) },
159 { LDAP_CONTROL_X_DOMAIN_SCOPE,
160 (int)offsetof(struct slap_control_ids, sc_domainScope),
161 SLAP_CTRL_GLOBAL|SLAP_CTRL_SEARCH|SLAP_CTRL_HIDE,
163 parseDomainScope, LDAP_SLIST_ENTRY_INITIALIZER(next) },
164 { LDAP_CONTROL_DONTUSECOPY,
165 (int)offsetof(struct slap_control_ids, sc_dontUseCopy),
166 SLAP_CTRL_GLOBAL|SLAP_CTRL_INTROGATE,
168 parseDontUseCopy, LDAP_SLIST_ENTRY_INITIALIZER(next) },
169 { LDAP_CONTROL_X_PERMISSIVE_MODIFY,
170 (int)offsetof(struct slap_control_ids, sc_permissiveModify),
171 SLAP_CTRL_MODIFY|SLAP_CTRL_HIDE,
173 parsePermissiveModify, LDAP_SLIST_ENTRY_INITIALIZER(next) },
174 #ifdef SLAP_CONTROL_X_TREE_DELETE
175 { LDAP_CONTROL_X_TREE_DELETE,
176 (int)offsetof(struct slap_control_ids, sc_treeDelete),
177 SLAP_CTRL_DELETE|SLAP_CTRL_HIDE,
179 parseTreeDelete, LDAP_SLIST_ENTRY_INITIALIZER(next) },
181 { LDAP_CONTROL_X_SEARCH_OPTIONS,
182 (int)offsetof(struct slap_control_ids, sc_searchOptions),
183 SLAP_CTRL_GLOBAL|SLAP_CTRL_SEARCH|SLAP_CTRL_HIDE,
185 parseSearchOptions, LDAP_SLIST_ENTRY_INITIALIZER(next) },
186 { LDAP_CONTROL_SUBENTRIES,
187 (int)offsetof(struct slap_control_ids, sc_subentries),
190 parseSubentries, LDAP_SLIST_ENTRY_INITIALIZER(next) },
192 (int)offsetof(struct slap_control_ids, sc_noOp),
193 SLAP_CTRL_ACCESS|SLAP_CTRL_HIDE,
195 parseNoOp, LDAP_SLIST_ENTRY_INITIALIZER(next) },
196 { LDAP_CONTROL_RELAX,
197 (int)offsetof(struct slap_control_ids, sc_relax),
198 SLAP_CTRL_GLOBAL|SLAP_CTRL_UPDATE|SLAP_CTRL_HIDE,
200 parseRelax, LDAP_SLIST_ENTRY_INITIALIZER(next) },
202 { LDAP_CONTROL_X_TXN_SPEC,
203 (int)offsetof(struct slap_control_ids, sc_txnSpec),
204 SLAP_CTRL_UPDATE|SLAP_CTRL_HIDE,
206 txn_spec_ctrl, LDAP_SLIST_ENTRY_INITIALIZER(next) },
208 { LDAP_CONTROL_MANAGEDSAIT,
209 (int)offsetof(struct slap_control_ids, sc_manageDSAit),
211 manageDSAit_extops, NULL,
212 parseManageDSAit, LDAP_SLIST_ENTRY_INITIALIZER(next) },
213 { LDAP_CONTROL_PROXY_AUTHZ,
214 (int)offsetof(struct slap_control_ids, sc_proxyAuthz),
215 SLAP_CTRL_GLOBAL|SLAP_CTRL_ACCESS,
216 proxy_authz_extops, NULL,
217 parseProxyAuthz, LDAP_SLIST_ENTRY_INITIALIZER(next) },
218 #ifdef SLAP_CONTROL_X_SESSION_TRACKING
219 { LDAP_CONTROL_X_SESSION_TRACKING,
220 (int)offsetof(struct slap_control_ids, sc_sessionTracking),
221 SLAP_CTRL_GLOBAL|SLAP_CTRL_ACCESS|SLAP_CTRL_BIND|SLAP_CTRL_HIDE,
222 session_tracking_extops, NULL,
223 parseSessionTracking, LDAP_SLIST_ENTRY_INITIALIZER(next) },
225 #ifdef SLAP_CONTROL_X_WHATFAILED
226 { LDAP_CONTROL_X_WHATFAILED,
227 (int)offsetof(struct slap_control_ids, sc_whatFailed),
228 SLAP_CTRL_GLOBAL|SLAP_CTRL_ACCESS|SLAP_CTRL_HIDE,
230 parseWhatFailed, LDAP_SLIST_ENTRY_INITIALIZER(next) },
232 #ifdef SLAP_CONTROL_X_LAZY_COMMIT
233 { LDAP_CONTROL_X_LAZY_COMMIT,
234 (int)offsetof(struct slap_control_ids, sc_lazyCommit),
235 SLAP_CTRL_GLOBAL|SLAP_CTRL_ACCESS|SLAP_CTRL_HIDE,
237 parseLazyCommit, LDAP_SLIST_ENTRY_INITIALIZER(next) },
240 { NULL, 0, 0, NULL, 0, NULL, LDAP_SLIST_ENTRY_INITIALIZER(next) }
243 static struct slap_control *
244 find_ctrl( const char *oid );
247 * Register a supported control.
249 * This can be called by an OpenLDAP plugin or, indirectly, by a
250 * SLAPI plugin calling slapi_register_supported_control().
252 * NOTE: if flags == 1 the control is replaced if already registered;
253 * otherwise registering an already registered control is not allowed.
256 register_supported_control2(const char *controloid,
257 slap_mask_t controlmask,
259 SLAP_CTRL_PARSE_FN *controlparsefn,
263 struct slap_control *sc = NULL;
265 BerVarray extendedopsbv = NULL;
267 if ( num_known_controls >= SLAP_MAX_CIDS ) {
268 Debug( LDAP_DEBUG_ANY, "Too many controls registered."
269 " Recompile slapd with SLAP_MAX_CIDS defined > %d\n",
270 SLAP_MAX_CIDS, 0, 0 );
274 if ( controloid == NULL ) {
275 return LDAP_PARAM_ERROR;
278 /* check if already registered */
279 for ( i = 0; slap_known_controls[ i ]; i++ ) {
280 if ( strcmp( controloid, slap_known_controls[ i ] ) == 0 ) {
282 Debug( LDAP_DEBUG_TRACE,
283 "Control %s already registered; replacing.\n",
285 /* (find and) replace existing handler */
286 sc = find_ctrl( controloid );
287 assert( sc != NULL );
291 Debug( LDAP_DEBUG_ANY,
292 "Control %s already registered.\n",
294 return LDAP_PARAM_ERROR;
298 /* turn compatible extended operations into bervals */
299 if ( controlexops != NULL ) {
302 for ( i = 0; controlexops[ i ]; i++ );
304 extendedopsbv = ber_memcalloc( i + 1, sizeof( struct berval ) );
305 if ( extendedopsbv == NULL ) {
306 return LDAP_NO_MEMORY;
309 for ( i = 0; controlexops[ i ]; i++ ) {
310 ber_str2bv( controlexops[ i ], 0, 1, &extendedopsbv[ i ] );
315 sc = (struct slap_control *)SLAP_MALLOC( sizeof( *sc ) );
317 ber_bvarray_free( extendedopsbv );
318 return LDAP_NO_MEMORY;
321 sc->sc_oid = ch_strdup( controloid );
322 sc->sc_cid = num_known_controls;
324 /* Update slap_known_controls, too. */
325 slap_known_controls[num_known_controls - 1] = sc->sc_oid;
326 slap_known_controls[num_known_controls++] = NULL;
328 LDAP_SLIST_NEXT( sc, sc_next ) = NULL;
329 LDAP_SLIST_INSERT_HEAD( &controls_list, sc, sc_next );
332 if ( sc->sc_extendedopsbv ) {
333 ber_bvarray_free( sc->sc_extendedopsbv );
334 sc->sc_extendedopsbv = NULL;
335 sc->sc_extendedops = NULL;
339 sc->sc_extendedopsbv = extendedopsbv;
340 sc->sc_mask = controlmask;
341 sc->sc_parse = controlparsefn;
343 *controlcid = sc->sc_cid;
349 #ifdef SLAP_CONFIG_DELETE
351 unregister_supported_control( const char *controloid )
353 struct slap_control *sc;
356 if ( controloid == NULL || (sc = find_ctrl( controloid )) == NULL ){
360 for ( i = 0; slap_known_controls[ i ]; i++ ) {
361 if ( strcmp( controloid, slap_known_controls[ i ] ) == 0 ) {
363 slap_known_controls[ i ] = slap_known_controls[ i+1 ];
364 } while ( slap_known_controls[ i++ ] );
365 num_known_controls--;
370 LDAP_SLIST_REMOVE(&controls_list, sc, slap_control, sc_next);
371 ch_free( sc->sc_oid );
372 if ( sc->sc_extendedopsbv != NULL ) {
373 ber_bvarray_free( sc->sc_extendedopsbv );
379 #endif /* SLAP_CONFIG_DELETE */
382 register_control_exop( const char *controloid, char *exopoid )
384 struct slap_control *sc = NULL;
385 BerVarray extendedopsbv;
389 if ( controloid == NULL || exopoid == NULL ) {
390 return LDAP_PARAM_ERROR;
393 for ( i = 0; slap_known_controls[ i ]; i++ ) {
394 if ( strcmp( controloid, slap_known_controls[ i ] ) == 0 ) {
395 sc = find_ctrl( controloid );
396 assert( sc != NULL );
402 Debug( LDAP_DEBUG_ANY, "register_control_exop: "
403 "Control %s not registered.\n",
405 return LDAP_PARAM_ERROR;
408 for ( i = 0; sc->sc_extendedops && sc->sc_extendedops[ i ]; i++ ) {
409 if ( strcmp( exopoid, sc->sc_extendedops[ i ] ) == 0 ) {
414 extendedops = ber_memrealloc( sc->sc_extendedops, (i + 2) * sizeof( char * ) );
415 if ( extendedops == NULL ) {
416 return LDAP_NO_MEMORY;
418 sc->sc_extendedops = extendedops;
420 extendedopsbv = ber_memrealloc( sc->sc_extendedopsbv, (i + 2) * sizeof( struct berval ) );
421 if ( extendedopsbv == NULL ) {
422 return LDAP_NO_MEMORY;
424 sc->sc_extendedopsbv = extendedopsbv;
426 extendedops[ i ] = exopoid;
427 extendedops[ i+1 ] = NULL;
429 ber_str2bv( exopoid, 0, 1, &extendedopsbv[ i ] );
430 BER_BVZERO( &extendedopsbv[ i+1 ] );
436 * One-time initialization of internal controls.
439 slap_controls_init( void )
445 for ( i = 0; control_defs[i].sc_oid != NULL; i++ ) {
446 int *cid = (int *)(((char *)&slap_cids) + control_defs[i].sc_cid );
447 rc = register_supported_control( control_defs[i].sc_oid,
448 control_defs[i].sc_mask, control_defs[i].sc_extendedops,
449 control_defs[i].sc_parse, cid );
450 if ( rc != LDAP_SUCCESS ) break;
457 * Free memory associated with list of supported controls.
460 controls_destroy( void )
462 struct slap_control *sc;
464 while ( !LDAP_SLIST_EMPTY(&controls_list) ) {
465 sc = LDAP_SLIST_FIRST(&controls_list);
466 LDAP_SLIST_REMOVE_HEAD(&controls_list, sc_next);
468 ch_free( sc->sc_oid );
469 if ( sc->sc_extendedopsbv != NULL ) {
470 ber_bvarray_free( sc->sc_extendedopsbv );
477 * Format the supportedControl attribute of the root DSE,
478 * detailing which controls are supported by the directory
482 controls_root_dse_info( Entry *e )
484 AttributeDescription *ad_supportedControl
485 = slap_schema.si_ad_supportedControl;
486 struct berval vals[2];
487 struct slap_control *sc;
489 vals[1].bv_val = NULL;
492 LDAP_SLIST_FOREACH( sc, &controls_list, sc_next ) {
493 if( sc->sc_mask & SLAP_CTRL_HIDE ) continue;
495 vals[0].bv_val = sc->sc_oid;
496 vals[0].bv_len = strlen( sc->sc_oid );
498 if ( attr_merge( e, ad_supportedControl, vals, NULL ) ) {
507 * Return a list of OIDs and operation masks for supported
508 * controls. Used by SLAPI.
511 get_supported_controls(char ***ctrloidsp,
512 slap_mask_t **ctrlmasks)
517 struct slap_control *sc;
521 LDAP_SLIST_FOREACH( sc, &controls_list, sc_next ) {
531 oids = (char **)SLAP_MALLOC( (n + 1) * sizeof(char *) );
532 if ( oids == NULL ) {
533 return LDAP_NO_MEMORY;
535 masks = (slap_mask_t *)SLAP_MALLOC( (n + 1) * sizeof(slap_mask_t) );
536 if ( masks == NULL ) {
538 return LDAP_NO_MEMORY;
543 LDAP_SLIST_FOREACH( sc, &controls_list, sc_next ) {
544 oids[n] = ch_strdup( sc->sc_oid );
545 masks[n] = sc->sc_mask;
558 * Find a control given its OID.
560 static struct slap_control *
561 find_ctrl( const char *oid )
563 struct slap_control *sc;
565 LDAP_SLIST_FOREACH( sc, &controls_list, sc_next ) {
566 if ( strcmp( oid, sc->sc_oid ) == 0 ) {
575 slap_find_control_id(
579 struct slap_control *ctrl = find_ctrl( oid );
581 if ( cid ) *cid = ctrl->sc_cid;
584 return LDAP_CONTROL_NOT_FOUND;
588 slap_global_control( Operation *op, const char *oid, int *cid )
590 struct slap_control *ctrl = find_ctrl( oid );
592 if ( ctrl == NULL ) {
593 /* should not be reachable */
594 Debug( LDAP_DEBUG_ANY,
595 "slap_global_control: unrecognized control: %s\n",
597 return LDAP_CONTROL_NOT_FOUND;
600 if ( cid ) *cid = ctrl->sc_cid;
602 if ( ( ctrl->sc_mask & SLAP_CTRL_GLOBAL ) ||
603 ( ( op->o_tag & LDAP_REQ_SEARCH ) &&
604 ( ctrl->sc_mask & SLAP_CTRL_GLOBAL_SEARCH ) ) )
606 return LDAP_COMPARE_TRUE;
610 Debug( LDAP_DEBUG_TRACE,
611 "slap_global_control: unavailable control: %s\n",
615 return LDAP_COMPARE_FALSE;
618 void slap_free_ctrls(
620 LDAPControl **ctrls )
624 if( ctrls == op->o_ctrls ) {
625 if( op->o_assertion != NULL ) {
626 filter_free_x( op, op->o_assertion, 1 );
627 op->o_assertion = NULL;
629 if( op->o_vrFilter != NULL) {
630 vrFilter_free( op, op->o_vrFilter );
631 op->o_vrFilter = NULL;
633 if( op->o_preread_attrs != NULL ) {
634 op->o_tmpfree( op->o_preread_attrs, op->o_tmpmemctx );
635 op->o_preread_attrs = NULL;
637 if( op->o_postread_attrs != NULL ) {
638 op->o_tmpfree( op->o_postread_attrs, op->o_tmpmemctx );
639 op->o_postread_attrs = NULL;
641 if( op->o_pagedresults_state != NULL ) {
642 op->o_tmpfree( op->o_pagedresults_state, op->o_tmpmemctx );
643 op->o_pagedresults_state = NULL;
647 for (i=0; ctrls[i]; i++) {
648 op->o_tmpfree(ctrls[i], op->o_tmpmemctx );
650 op->o_tmpfree( ctrls, op->o_tmpmemctx );
656 LDAPControl **ctrls )
659 LDAPControl **ctrlsp;
661 if ( rs->sr_ctrls ) {
662 for ( ; rs->sr_ctrls[ i ]; i++ ) ;
665 for ( j=0; ctrls[j]; j++ ) ;
667 ctrlsp = op->o_tmpalloc(( i+j+1 )*sizeof(LDAPControl *), op->o_tmpmemctx );
669 if ( rs->sr_ctrls ) {
670 for ( ; rs->sr_ctrls[i]; i++ )
671 ctrlsp[i] = rs->sr_ctrls[i];
673 for ( j=0; ctrls[j]; j++)
674 ctrlsp[i++] = ctrls[j];
677 if ( rs->sr_flags & REP_CTRLS_MUSTBEFREED )
678 op->o_tmpfree( rs->sr_ctrls, op->o_tmpmemctx );
679 rs->sr_ctrls = ctrlsp;
680 rs->sr_flags |= REP_CTRLS_MUSTBEFREED;
687 LDAPControl *control,
690 struct slap_control *sc;
691 int rc = LDAP_SUCCESS;
693 sc = find_ctrl( control->ldctl_oid );
695 /* recognized control */
697 switch( op->o_tag ) {
699 tagmask = SLAP_CTRL_ADD;
702 tagmask = SLAP_CTRL_BIND;
704 case LDAP_REQ_COMPARE:
705 tagmask = SLAP_CTRL_COMPARE;
707 case LDAP_REQ_DELETE:
708 tagmask = SLAP_CTRL_DELETE;
710 case LDAP_REQ_MODIFY:
711 tagmask = SLAP_CTRL_MODIFY;
713 case LDAP_REQ_RENAME:
714 tagmask = SLAP_CTRL_RENAME;
716 case LDAP_REQ_SEARCH:
717 tagmask = SLAP_CTRL_SEARCH;
719 case LDAP_REQ_UNBIND:
720 tagmask = SLAP_CTRL_UNBIND;
722 case LDAP_REQ_ABANDON:
723 tagmask = SLAP_CTRL_ABANDON;
725 case LDAP_REQ_EXTENDED:
727 assert( op->ore_reqoid.bv_val != NULL );
728 if( sc->sc_extendedopsbv != NULL ) {
730 for( i=0; !BER_BVISNULL( &sc->sc_extendedopsbv[i] ); i++ ) {
731 if( bvmatch( &op->ore_reqoid,
732 &sc->sc_extendedopsbv[i] ) )
741 *text = "controls internal error";
745 if (( sc->sc_mask & tagmask ) == tagmask ) {
746 /* available extension */
747 if ( sc->sc_parse ) {
748 rc = sc->sc_parse( op, rs, control );
749 assert( rc != LDAP_UNAVAILABLE_CRITICAL_EXTENSION );
751 } else if ( control->ldctl_iscritical ) {
752 *text = "not yet implemented";
757 } else if ( control->ldctl_iscritical ) {
758 /* unavailable CRITICAL control */
759 *text = "critical extension is unavailable";
760 rc = LDAP_UNAVAILABLE_CRITICAL_EXTENSION;
763 } else if ( control->ldctl_iscritical ) {
764 /* unrecognized CRITICAL control */
765 *text = "critical extension is not recognized";
766 rc = LDAP_UNAVAILABLE_CRITICAL_EXTENSION;
778 return get_ctrls2( op, rs, sendres, LDAP_TAG_CONTROLS );
792 BerElement *ber = op->o_ber;
794 #ifdef SLAP_CONTROL_X_WHATFAILED
795 /* NOTE: right now, slapd checks the validity of each control
796 * while parsing. As a consequence, it can only detect one
797 * cause of failure at a time. This results in returning
798 * exactly one OID with the whatFailed control, or no control
801 char *failed_oid = NULL;
804 len = ber_pvt_ber_remaining(ber);
808 rs->sr_err = LDAP_SUCCESS;
812 if(( tag = ber_peek_tag( ber, &len )) != ctag ) {
813 if( tag == LBER_ERROR ) {
814 rs->sr_err = SLAPD_DISCONNECT;
815 rs->sr_text = "unexpected data in PDU";
821 Debug( LDAP_DEBUG_TRACE,
822 "=> get_ctrls\n", 0, 0, 0 );
824 if( op->o_protocol < LDAP_VERSION3 ) {
825 rs->sr_err = SLAPD_DISCONNECT;
826 rs->sr_text = "controls require LDAPv3";
830 /* one for first control, one for termination */
831 op->o_ctrls = op->o_tmpalloc( 2 * sizeof(LDAPControl *), op->o_tmpmemctx );
834 if( op->ctrls == NULL ) {
835 rs->sr_err = LDAP_NO_MEMORY;
836 rs->sr_text = "no memory";
841 op->o_ctrls[nctrls] = NULL;
843 /* step through each element */
844 for( tag = ber_first_element( ber, &len, &opaque );
846 tag = ber_next_element( ber, &len, opaque ) )
849 LDAPControl **tctrls;
851 c = op->o_tmpalloc( sizeof(LDAPControl), op->o_tmpmemctx );
852 memset(c, 0, sizeof(LDAPControl));
854 /* allocate pointer space for current controls (nctrls)
855 * + this control + extra NULL
857 tctrls = op->o_tmprealloc( op->o_ctrls,
858 (nctrls+2) * sizeof(LDAPControl *), op->o_tmpmemctx );
861 if( tctrls == NULL ) {
863 ldap_controls_free(op->o_ctrls);
866 rs->sr_err = LDAP_NO_MEMORY;
867 rs->sr_text = "no memory";
871 op->o_ctrls = tctrls;
873 op->o_ctrls[nctrls++] = c;
874 op->o_ctrls[nctrls] = NULL;
876 tag = ber_scanf( ber, "{m" /*}*/, &bv );
877 c->ldctl_oid = bv.bv_val;
879 if( tag == LBER_ERROR ) {
880 Debug( LDAP_DEBUG_TRACE, "=> get_ctrls: get oid failed.\n",
883 slap_free_ctrls( op, op->o_ctrls );
885 rs->sr_err = SLAPD_DISCONNECT;
886 rs->sr_text = "decoding controls error";
889 } else if( c->ldctl_oid == NULL ) {
890 Debug( LDAP_DEBUG_TRACE,
891 "get_ctrls: conn %lu got empty OID.\n",
892 op->o_connid, 0, 0 );
894 slap_free_ctrls( op, op->o_ctrls );
896 rs->sr_err = LDAP_PROTOCOL_ERROR;
897 rs->sr_text = "OID field is empty";
901 tag = ber_peek_tag( ber, &len );
903 if( tag == LBER_BOOLEAN ) {
905 tag = ber_scanf( ber, "b", &crit );
907 if( tag == LBER_ERROR ) {
908 Debug( LDAP_DEBUG_TRACE, "=> get_ctrls: get crit failed.\n",
910 slap_free_ctrls( op, op->o_ctrls );
912 rs->sr_err = SLAPD_DISCONNECT;
913 rs->sr_text = "decoding controls error";
917 c->ldctl_iscritical = (crit != 0);
918 tag = ber_peek_tag( ber, &len );
921 if( tag == LBER_OCTETSTRING ) {
922 tag = ber_scanf( ber, "m", &c->ldctl_value );
924 if( tag == LBER_ERROR ) {
925 Debug( LDAP_DEBUG_TRACE, "=> get_ctrls: conn %lu: "
926 "%s (%scritical): get value failed.\n",
927 op->o_connid, c->ldctl_oid,
928 c->ldctl_iscritical ? "" : "non" );
929 slap_free_ctrls( op, op->o_ctrls );
931 rs->sr_err = SLAPD_DISCONNECT;
932 rs->sr_text = "decoding controls error";
937 Debug( LDAP_DEBUG_TRACE,
938 "=> get_ctrls: oid=\"%s\" (%scritical)\n",
939 c->ldctl_oid, c->ldctl_iscritical ? "" : "non", 0 );
941 rs->sr_err = slap_parse_ctrl( op, rs, c, &rs->sr_text );
942 if ( rs->sr_err != LDAP_SUCCESS ) {
943 #ifdef SLAP_CONTROL_X_WHATFAILED
944 failed_oid = c->ldctl_oid;
951 Debug( LDAP_DEBUG_TRACE,
952 "<= get_ctrls: n=%d rc=%d err=\"%s\"\n",
953 nctrls, rs->sr_err, rs->sr_text ? rs->sr_text : "");
955 if( sendres && rs->sr_err != LDAP_SUCCESS ) {
956 if( rs->sr_err == SLAPD_DISCONNECT ) {
957 rs->sr_err = LDAP_PROTOCOL_ERROR;
958 send_ldap_disconnect( op, rs );
959 rs->sr_err = SLAPD_DISCONNECT;
961 #ifdef SLAP_CONTROL_X_WHATFAILED
962 /* might have not been parsed yet? */
963 if ( failed_oid != NULL ) {
964 if ( !get_whatFailed( op ) ) {
967 /* step through each remaining element */
968 for ( ; tag != LBER_ERROR; tag = ber_next_element( ber, &len, opaque ) )
970 LDAPControl c = { 0 };
972 tag = ber_scanf( ber, "{m" /*}*/, &bv );
973 c.ldctl_oid = bv.bv_val;
975 if ( tag == LBER_ERROR ) {
976 slap_free_ctrls( op, op->o_ctrls );
980 } else if ( c.ldctl_oid == NULL ) {
981 slap_free_ctrls( op, op->o_ctrls );
986 tag = ber_peek_tag( ber, &len );
987 if ( tag == LBER_BOOLEAN ) {
989 tag = ber_scanf( ber, "b", &crit );
990 if( tag == LBER_ERROR ) {
991 slap_free_ctrls( op, op->o_ctrls );
996 tag = ber_peek_tag( ber, &len );
999 if ( tag == LBER_OCTETSTRING ) {
1000 tag = ber_scanf( ber, "m", &c.ldctl_value );
1002 if( tag == LBER_ERROR ) {
1003 slap_free_ctrls( op, op->o_ctrls );
1009 if ( strcmp( c.ldctl_oid, LDAP_CONTROL_X_WHATFAILED ) == 0 ) {
1011 slap_parse_ctrl( op, rs, &c, &text );
1017 if ( get_whatFailed( op ) ) {
1019 oids[ 0 ] = failed_oid;
1021 slap_ctrl_whatFailed_add( op, rs, oids );
1026 send_ldap_result( op, rs );
1034 slap_remove_control(
1038 BI_chk_controls fnc )
1042 switch ( op->o_ctrlflag[ ctrl ] ) {
1043 case SLAP_CONTROL_NONCRITICAL:
1044 for ( i = 0, j = -1; op->o_ctrls[ i ] != NULL; i++ ) {
1045 if ( strcmp( op->o_ctrls[ i ]->ldctl_oid,
1046 slap_known_controls[ ctrl - 1 ] ) == 0 )
1053 rs->sr_err = LDAP_OTHER;
1058 (void)fnc( op, rs );
1061 op->o_tmpfree( op->o_ctrls[ j ], op->o_tmpmemctx );
1064 AC_MEMCPY( &op->o_ctrls[ j ], &op->o_ctrls[ j + 1 ],
1065 ( i - j ) * sizeof( LDAPControl * ) );
1068 op->o_tmpfree( op->o_ctrls, op->o_tmpmemctx );
1072 op->o_ctrlflag[ ctrl ] = SLAP_CONTROL_IGNORED;
1074 Debug( LDAP_DEBUG_ANY, "%s: "
1075 "non-critical control \"%s\" not supported; stripped.\n",
1076 op->o_log_prefix, slap_known_controls[ ctrl ], 0 );
1079 case SLAP_CONTROL_IGNORED:
1080 case SLAP_CONTROL_NONE:
1081 rs->sr_err = SLAP_CB_CONTINUE;
1084 case SLAP_CONTROL_CRITICAL:
1085 rs->sr_err = LDAP_UNAVAILABLE_CRITICAL_EXTENSION;
1087 (void)fnc( op, rs );
1089 Debug( LDAP_DEBUG_ANY, "%s: "
1090 "critical control \"%s\" not supported.\n",
1091 op->o_log_prefix, slap_known_controls[ ctrl ], 0 );
1095 /* handle all cases! */
1102 static int parseDontUseCopy (
1107 if ( op->o_dontUseCopy != SLAP_CONTROL_NONE ) {
1108 rs->sr_text = "dontUseCopy control specified multiple times";
1109 return LDAP_PROTOCOL_ERROR;
1112 if ( !BER_BVISNULL( &ctrl->ldctl_value )) {
1113 rs->sr_text = "dontUseCopy control value not absent";
1114 return LDAP_PROTOCOL_ERROR;
1117 if ( ( global_disallows & SLAP_DISALLOW_DONTUSECOPY_N_CRIT )
1118 && !ctrl->ldctl_iscritical )
1120 rs->sr_text = "dontUseCopy criticality of FALSE not allowed";
1121 return LDAP_PROTOCOL_ERROR;
1124 op->o_dontUseCopy = ctrl->ldctl_iscritical
1125 ? SLAP_CONTROL_CRITICAL
1126 : SLAP_CONTROL_NONCRITICAL;
1128 return LDAP_SUCCESS;
1131 static int parseRelax (
1136 if ( op->o_relax != SLAP_CONTROL_NONE ) {
1137 rs->sr_text = "relax control specified multiple times";
1138 return LDAP_PROTOCOL_ERROR;
1141 if ( !BER_BVISNULL( &ctrl->ldctl_value )) {
1142 rs->sr_text = "relax control value not absent";
1143 return LDAP_PROTOCOL_ERROR;
1146 op->o_relax = ctrl->ldctl_iscritical
1147 ? SLAP_CONTROL_CRITICAL
1148 : SLAP_CONTROL_NONCRITICAL;
1150 return LDAP_SUCCESS;
1153 static int parseManageDSAit (
1158 if ( op->o_managedsait != SLAP_CONTROL_NONE ) {
1159 rs->sr_text = "manageDSAit control specified multiple times";
1160 return LDAP_PROTOCOL_ERROR;
1163 if ( !BER_BVISNULL( &ctrl->ldctl_value )) {
1164 rs->sr_text = "manageDSAit control value not absent";
1165 return LDAP_PROTOCOL_ERROR;
1168 op->o_managedsait = ctrl->ldctl_iscritical
1169 ? SLAP_CONTROL_CRITICAL
1170 : SLAP_CONTROL_NONCRITICAL;
1172 return LDAP_SUCCESS;
1175 static int parseProxyAuthz (
1181 struct berval dn = BER_BVNULL;
1183 if ( op->o_proxy_authz != SLAP_CONTROL_NONE ) {
1184 rs->sr_text = "proxy authorization control specified multiple times";
1185 return LDAP_PROTOCOL_ERROR;
1188 if ( BER_BVISNULL( &ctrl->ldctl_value )) {
1189 rs->sr_text = "proxy authorization control value absent";
1190 return LDAP_PROTOCOL_ERROR;
1193 if ( ( global_disallows & SLAP_DISALLOW_PROXY_AUTHZ_N_CRIT )
1194 && !ctrl->ldctl_iscritical )
1196 rs->sr_text = "proxied authorization criticality of FALSE not allowed";
1197 return LDAP_PROTOCOL_ERROR;
1200 if ( !( global_allows & SLAP_ALLOW_PROXY_AUTHZ_ANON )
1201 && BER_BVISEMPTY( &op->o_ndn ) )
1203 rs->sr_text = "anonymous proxied authorization not allowed";
1204 return LDAP_PROXIED_AUTHORIZATION_DENIED;
1207 op->o_proxy_authz = ctrl->ldctl_iscritical
1208 ? SLAP_CONTROL_CRITICAL
1209 : SLAP_CONTROL_NONCRITICAL;
1211 Debug( LDAP_DEBUG_ARGS,
1212 "parseProxyAuthz: conn %lu authzid=\"%s\"\n",
1214 ctrl->ldctl_value.bv_len ? ctrl->ldctl_value.bv_val : "anonymous",
1217 if ( BER_BVISEMPTY( &ctrl->ldctl_value )) {
1218 Debug( LDAP_DEBUG_TRACE,
1219 "parseProxyAuthz: conn=%lu anonymous\n",
1220 op->o_connid, 0, 0 );
1223 if ( !BER_BVISNULL( &op->o_ndn ) ) {
1224 op->o_ndn.bv_val[ 0 ] = '\0';
1226 op->o_ndn.bv_len = 0;
1228 if ( !BER_BVISNULL( &op->o_dn ) ) {
1229 op->o_dn.bv_val[ 0 ] = '\0';
1231 op->o_dn.bv_len = 0;
1233 return LDAP_SUCCESS;
1236 rc = slap_sasl_getdn( op->o_conn, op, &ctrl->ldctl_value,
1237 NULL, &dn, SLAP_GETDN_AUTHZID );
1239 /* FIXME: empty DN in proxyAuthz control should be legal... */
1240 if( rc != LDAP_SUCCESS /* || !dn.bv_len */ ) {
1242 ch_free( dn.bv_val );
1244 rs->sr_text = "authzId mapping failed";
1245 return LDAP_PROXIED_AUTHORIZATION_DENIED;
1248 Debug( LDAP_DEBUG_TRACE,
1249 "parseProxyAuthz: conn=%lu \"%s\"\n",
1251 dn.bv_len ? dn.bv_val : "(NULL)", 0 );
1253 rc = slap_sasl_authorized( op, &op->o_ndn, &dn );
1256 ch_free( dn.bv_val );
1257 rs->sr_text = "not authorized to assume identity";
1258 return LDAP_PROXIED_AUTHORIZATION_DENIED;
1261 ch_free( op->o_ndn.bv_val );
1264 * NOTE: since slap_sasl_getdn() returns a normalized dn,
1265 * from now on op->o_dn is normalized
1268 ber_bvreplace( &op->o_dn, &dn );
1270 Statslog( LDAP_DEBUG_STATS, "%s PROXYAUTHZ dn=\"%s\"\n",
1271 op->o_log_prefix, dn.bv_val, 0, 0, 0 );
1273 return LDAP_SUCCESS;
1276 static int parseNoOp (
1281 if ( op->o_noop != SLAP_CONTROL_NONE ) {
1282 rs->sr_text = "noop control specified multiple times";
1283 return LDAP_PROTOCOL_ERROR;
1286 if ( !BER_BVISNULL( &ctrl->ldctl_value ) ) {
1287 rs->sr_text = "noop control value not empty";
1288 return LDAP_PROTOCOL_ERROR;
1291 op->o_noop = ctrl->ldctl_iscritical
1292 ? SLAP_CONTROL_CRITICAL
1293 : SLAP_CONTROL_NONCRITICAL;
1295 return LDAP_SUCCESS;
1298 static int parsePagedResults (
1303 BerElementBuffer berbuf;
1304 BerElement *ber = (BerElement *)&berbuf;
1305 struct berval cookie;
1306 PagedResultsState *ps;
1307 int rc = LDAP_SUCCESS;
1311 if ( op->o_pagedresults != SLAP_CONTROL_NONE ) {
1312 rs->sr_text = "paged results control specified multiple times";
1313 return LDAP_PROTOCOL_ERROR;
1316 if ( BER_BVISNULL( &ctrl->ldctl_value ) ) {
1317 rs->sr_text = "paged results control value is absent";
1318 return LDAP_PROTOCOL_ERROR;
1321 if ( BER_BVISEMPTY( &ctrl->ldctl_value ) ) {
1322 rs->sr_text = "paged results control value is empty";
1323 return LDAP_PROTOCOL_ERROR;
1326 /* Parse the control value
1327 * realSearchControlValue ::= SEQUENCE {
1328 * size INTEGER (0..maxInt),
1329 * -- requested page size from client
1330 * -- result set size estimate from server
1331 * cookie OCTET STRING
1334 ber_init2( ber, &ctrl->ldctl_value, LBER_USE_DER );
1336 tag = ber_scanf( ber, "{im}", &size, &cookie );
1338 if ( tag == LBER_ERROR ) {
1339 rs->sr_text = "paged results control could not be decoded";
1340 rc = LDAP_PROTOCOL_ERROR;
1345 rs->sr_text = "paged results control size invalid";
1346 rc = LDAP_PROTOCOL_ERROR;
1350 ps = op->o_tmpalloc( sizeof(PagedResultsState), op->o_tmpmemctx );
1351 *ps = op->o_conn->c_pagedresults_state;
1353 ps->ps_cookieval = cookie;
1354 op->o_pagedresults_state = ps;
1355 if ( !cookie.bv_len ) {
1358 /* taint ps_cookie, to detect whether it's set */
1359 op->o_conn->c_pagedresults_state.ps_cookie = NOID;
1362 /* NOTE: according to RFC 2696 3.:
1364 If the page size is greater than or equal to the sizeLimit value, the
1365 server should ignore the control as the request can be satisfied in a
1368 * NOTE: this assumes that the op->ors_slimit be set
1369 * before the controls are parsed.
1372 if ( op->ors_slimit > 0 && size >= op->ors_slimit ) {
1373 op->o_pagedresults = SLAP_CONTROL_IGNORED;
1375 } else if ( ctrl->ldctl_iscritical ) {
1376 op->o_pagedresults = SLAP_CONTROL_CRITICAL;
1379 op->o_pagedresults = SLAP_CONTROL_NONCRITICAL;
1386 #ifdef SLAP_CONTROL_X_SORTEDRESULTS
1387 static int parseSortedResults (
1392 int rc = LDAP_SUCCESS;
1394 if ( op->o_sortedresults != SLAP_CONTROL_NONE ) {
1395 rs->sr_text = "sorted results control specified multiple times";
1396 return LDAP_PROTOCOL_ERROR;
1399 if ( BER_BVISNULL( &ctrl->ldctl_value ) ) {
1400 rs->sr_text = "sorted results control value is absent";
1401 return LDAP_PROTOCOL_ERROR;
1404 if ( BER_BVISEMPTY( &ctrl->ldctl_value ) ) {
1405 rs->sr_text = "sorted results control value is empty";
1406 return LDAP_PROTOCOL_ERROR;
1409 /* blow off parsing the value */
1411 op->o_sortedresults = ctrl->ldctl_iscritical
1412 ? SLAP_CONTROL_CRITICAL
1413 : SLAP_CONTROL_NONCRITICAL;
1419 static int parseAssert (
1425 struct berval fstr = BER_BVNULL;
1427 if ( op->o_assert != SLAP_CONTROL_NONE ) {
1428 rs->sr_text = "assert control specified multiple times";
1429 return LDAP_PROTOCOL_ERROR;
1432 if ( BER_BVISNULL( &ctrl->ldctl_value )) {
1433 rs->sr_text = "assert control value is absent";
1434 return LDAP_PROTOCOL_ERROR;
1437 if ( BER_BVISEMPTY( &ctrl->ldctl_value )) {
1438 rs->sr_text = "assert control value is empty";
1439 return LDAP_PROTOCOL_ERROR;
1442 ber = ber_init( &(ctrl->ldctl_value) );
1444 rs->sr_text = "assert control: internal error";
1448 rs->sr_err = get_filter( op, ber, (Filter **)&(op->o_assertion),
1450 (void) ber_free( ber, 1 );
1451 if( rs->sr_err != LDAP_SUCCESS ) {
1452 if( rs->sr_err == SLAPD_DISCONNECT ) {
1453 rs->sr_err = LDAP_PROTOCOL_ERROR;
1454 send_ldap_disconnect( op, rs );
1455 rs->sr_err = SLAPD_DISCONNECT;
1457 send_ldap_result( op, rs );
1459 if( op->o_assertion != NULL ) {
1460 filter_free_x( op, op->o_assertion, 1 );
1461 op->o_assertion = NULL;
1467 filter2bv_x( op, op->o_assertion, &fstr );
1469 Debug( LDAP_DEBUG_ARGS, "parseAssert: conn %ld assert: %s\n",
1470 op->o_connid, fstr.bv_len ? fstr.bv_val : "empty" , 0 );
1471 op->o_tmpfree( fstr.bv_val, op->o_tmpmemctx );
1474 op->o_assert = ctrl->ldctl_iscritical
1475 ? SLAP_CONTROL_CRITICAL
1476 : SLAP_CONTROL_NONCRITICAL;
1478 rs->sr_err = LDAP_SUCCESS;
1479 return LDAP_SUCCESS;
1482 #define READMSG(post, msg) \
1483 ( post ? "postread control: " msg : "preread control: " msg )
1492 ber_len_t siz, off, i;
1494 AttributeName *an = NULL;
1496 if ( ( post && op->o_postread != SLAP_CONTROL_NONE ) ||
1497 ( !post && op->o_preread != SLAP_CONTROL_NONE ) )
1499 rs->sr_text = READMSG( post, "specified multiple times" );
1500 return LDAP_PROTOCOL_ERROR;
1503 if ( BER_BVISNULL( &ctrl->ldctl_value ) ) {
1504 rs->sr_text = READMSG( post, "value is absent" );
1505 return LDAP_PROTOCOL_ERROR;
1508 if ( BER_BVISEMPTY( &ctrl->ldctl_value ) ) {
1509 rs->sr_text = READMSG( post, "value is empty" );
1510 return LDAP_PROTOCOL_ERROR;
1514 if ( op->o_txnSpec ) { /* temporary limitation */
1515 rs->sr_text = READMSG( post, "cannot perform in transaction" );
1516 return LDAP_UNWILLING_TO_PERFORM;
1520 ber = ber_init( &ctrl->ldctl_value );
1521 if ( ber == NULL ) {
1522 rs->sr_text = READMSG( post, "internal error" );
1526 rs->sr_err = LDAP_SUCCESS;
1527 siz = sizeof( AttributeName );
1528 off = offsetof( AttributeName, an_name );
1529 if ( ber_scanf( ber, "{M}", &an, &siz, off ) == LBER_ERROR ) {
1530 rs->sr_text = READMSG( post, "decoding error" );
1531 rs->sr_err = LDAP_PROTOCOL_ERROR;
1535 for ( i = 0; i < siz; i++ ) {
1536 const char *dummy = NULL;
1539 an[i].an_desc = NULL;
1542 rc = slap_bv2ad( &an[i].an_name, &an[i].an_desc, &dummy );
1543 if ( rc == LDAP_SUCCESS ) {
1544 an[i].an_name = an[i].an_desc->ad_cname;
1548 static struct berval special_attrs[] = {
1549 BER_BVC( LDAP_NO_ATTRS ),
1550 BER_BVC( LDAP_ALL_USER_ATTRIBUTES ),
1551 BER_BVC( LDAP_ALL_OPERATIONAL_ATTRIBUTES ),
1555 /* deal with special attribute types */
1556 for ( j = 0; !BER_BVISNULL( &special_attrs[ j ] ); j++ ) {
1557 if ( bvmatch( &an[i].an_name, &special_attrs[ j ] ) ) {
1558 an[i].an_name = special_attrs[ j ];
1563 if ( BER_BVISNULL( &special_attrs[ j ] ) && ctrl->ldctl_iscritical ) {
1565 rs->sr_text = dummy ? dummy
1566 : READMSG( post, "unknown attributeType" );
1573 op->o_postread_attrs = an;
1574 op->o_postread = ctrl->ldctl_iscritical
1575 ? SLAP_CONTROL_CRITICAL
1576 : SLAP_CONTROL_NONCRITICAL;
1578 op->o_preread_attrs = an;
1579 op->o_preread = ctrl->ldctl_iscritical
1580 ? SLAP_CONTROL_CRITICAL
1581 : SLAP_CONTROL_NONCRITICAL;
1585 (void) ber_free( ber, 1 );
1589 static int parsePreRead (
1594 return parseReadAttrs( op, rs, ctrl, 0 );
1597 static int parsePostRead (
1602 return parseReadAttrs( op, rs, ctrl, 1 );
1605 static int parseValuesReturnFilter (
1611 struct berval fstr = BER_BVNULL;
1613 if ( op->o_valuesreturnfilter != SLAP_CONTROL_NONE ) {
1614 rs->sr_text = "valuesReturnFilter control specified multiple times";
1615 return LDAP_PROTOCOL_ERROR;
1618 if ( BER_BVISNULL( &ctrl->ldctl_value )) {
1619 rs->sr_text = "valuesReturnFilter control value is absent";
1620 return LDAP_PROTOCOL_ERROR;
1623 if ( BER_BVISEMPTY( &ctrl->ldctl_value )) {
1624 rs->sr_text = "valuesReturnFilter control value is empty";
1625 return LDAP_PROTOCOL_ERROR;
1628 ber = ber_init( &(ctrl->ldctl_value) );
1630 rs->sr_text = "internal error";
1634 rs->sr_err = get_vrFilter( op, ber,
1635 (ValuesReturnFilter **)&(op->o_vrFilter), &rs->sr_text);
1637 (void) ber_free( ber, 1 );
1639 if( rs->sr_err != LDAP_SUCCESS ) {
1640 if( rs->sr_err == SLAPD_DISCONNECT ) {
1641 rs->sr_err = LDAP_PROTOCOL_ERROR;
1642 send_ldap_disconnect( op, rs );
1643 rs->sr_err = SLAPD_DISCONNECT;
1645 send_ldap_result( op, rs );
1647 if( op->o_vrFilter != NULL) vrFilter_free( op, op->o_vrFilter );
1651 vrFilter2bv( op, op->o_vrFilter, &fstr );
1654 Debug( LDAP_DEBUG_ARGS, " vrFilter: %s\n",
1655 fstr.bv_len ? fstr.bv_val : "empty", 0, 0 );
1656 op->o_tmpfree( fstr.bv_val, op->o_tmpmemctx );
1659 op->o_valuesreturnfilter = ctrl->ldctl_iscritical
1660 ? SLAP_CONTROL_CRITICAL
1661 : SLAP_CONTROL_NONCRITICAL;
1663 rs->sr_err = LDAP_SUCCESS;
1664 return LDAP_SUCCESS;
1667 static int parseSubentries (
1672 if ( op->o_subentries != SLAP_CONTROL_NONE ) {
1673 rs->sr_text = "subentries control specified multiple times";
1674 return LDAP_PROTOCOL_ERROR;
1677 /* FIXME: should use BER library */
1678 if( ( ctrl->ldctl_value.bv_len != 3 )
1679 || ( ctrl->ldctl_value.bv_val[0] != 0x01 )
1680 || ( ctrl->ldctl_value.bv_val[1] != 0x01 ))
1682 rs->sr_text = "subentries control value encoding is bogus";
1683 return LDAP_PROTOCOL_ERROR;
1686 op->o_subentries = ctrl->ldctl_iscritical
1687 ? SLAP_CONTROL_CRITICAL
1688 : SLAP_CONTROL_NONCRITICAL;
1690 if (ctrl->ldctl_value.bv_val[2]) {
1691 set_subentries_visibility( op );
1694 return LDAP_SUCCESS;
1697 static int parsePermissiveModify (
1702 if ( op->o_permissive_modify != SLAP_CONTROL_NONE ) {
1703 rs->sr_text = "permissiveModify control specified multiple times";
1704 return LDAP_PROTOCOL_ERROR;
1707 if ( !BER_BVISNULL( &ctrl->ldctl_value )) {
1708 rs->sr_text = "permissiveModify control value not absent";
1709 return LDAP_PROTOCOL_ERROR;
1712 op->o_permissive_modify = ctrl->ldctl_iscritical
1713 ? SLAP_CONTROL_CRITICAL
1714 : SLAP_CONTROL_NONCRITICAL;
1716 return LDAP_SUCCESS;
1719 static int parseDomainScope (
1724 if ( op->o_domain_scope != SLAP_CONTROL_NONE ) {
1725 rs->sr_text = "domainScope control specified multiple times";
1726 return LDAP_PROTOCOL_ERROR;
1729 if ( !BER_BVISNULL( &ctrl->ldctl_value )) {
1730 rs->sr_text = "domainScope control value not absent";
1731 return LDAP_PROTOCOL_ERROR;
1734 op->o_domain_scope = ctrl->ldctl_iscritical
1735 ? SLAP_CONTROL_CRITICAL
1736 : SLAP_CONTROL_NONCRITICAL;
1738 return LDAP_SUCCESS;
1741 #ifdef SLAP_CONTROL_X_TREE_DELETE
1742 static int parseTreeDelete (
1747 if ( op->o_tree_delete != SLAP_CONTROL_NONE ) {
1748 rs->sr_text = "treeDelete control specified multiple times";
1749 return LDAP_PROTOCOL_ERROR;
1752 if ( !BER_BVISNULL( &ctrl->ldctl_value )) {
1753 rs->sr_text = "treeDelete control value not absent";
1754 return LDAP_PROTOCOL_ERROR;
1757 op->o_tree_delete = ctrl->ldctl_iscritical
1758 ? SLAP_CONTROL_CRITICAL
1759 : SLAP_CONTROL_NONCRITICAL;
1761 return LDAP_SUCCESS;
1765 static int parseSearchOptions (
1771 ber_int_t search_flags;
1774 if ( BER_BVISNULL( &ctrl->ldctl_value )) {
1775 rs->sr_text = "searchOptions control value is absent";
1776 return LDAP_PROTOCOL_ERROR;
1779 if ( BER_BVISEMPTY( &ctrl->ldctl_value )) {
1780 rs->sr_text = "searchOptions control value is empty";
1781 return LDAP_PROTOCOL_ERROR;
1784 ber = ber_init( &ctrl->ldctl_value );
1786 rs->sr_text = "internal error";
1790 tag = ber_scanf( ber, "{i}", &search_flags );
1791 (void) ber_free( ber, 1 );
1793 if ( tag == LBER_ERROR ) {
1794 rs->sr_text = "searchOptions control decoding error";
1795 return LDAP_PROTOCOL_ERROR;
1798 if ( search_flags & ~(LDAP_SEARCH_FLAG_DOMAIN_SCOPE) ) {
1799 /* Search flags not recognised so far,
1801 * LDAP_SEARCH_FLAG_PHANTOM_ROOT
1803 if ( ctrl->ldctl_iscritical ) {
1804 rs->sr_text = "searchOptions contained unrecognized flag";
1805 return LDAP_UNWILLING_TO_PERFORM;
1809 Debug( LDAP_DEBUG_TRACE,
1810 "searchOptions: conn=%lu unrecognized flag(s) 0x%x (non-critical)\n",
1811 op->o_connid, (unsigned)search_flags, 0 );
1813 return LDAP_SUCCESS;
1816 if ( search_flags & LDAP_SEARCH_FLAG_DOMAIN_SCOPE ) {
1817 if ( op->o_domain_scope != SLAP_CONTROL_NONE ) {
1818 rs->sr_text = "searchOptions control specified multiple times "
1819 "or with domainScope control";
1820 return LDAP_PROTOCOL_ERROR;
1823 op->o_domain_scope = ctrl->ldctl_iscritical
1824 ? SLAP_CONTROL_CRITICAL
1825 : SLAP_CONTROL_NONCRITICAL;
1828 return LDAP_SUCCESS;
1831 #ifdef SLAP_CONTROL_X_SESSION_TRACKING
1832 struct berval session_tracking_formats[] = {
1833 BER_BVC( LDAP_CONTROL_X_SESSION_TRACKING_RADIUS_ACCT_SESSION_ID ),
1834 BER_BVC( "RADIUS-Acct-Session-Id" ),
1835 BER_BVC( LDAP_CONTROL_X_SESSION_TRACKING_RADIUS_ACCT_MULTI_SESSION_ID ),
1836 BER_BVC( "RADIUS-Acct-Multi-Session-Id" ),
1837 BER_BVC( LDAP_CONTROL_X_SESSION_TRACKING_USERNAME ),
1838 BER_BVC( "USERNAME" ),
1843 static int parseSessionTracking(
1853 struct berval sessionSourceIp = BER_BVNULL,
1854 sessionSourceName = BER_BVNULL,
1855 formatOID = BER_BVNULL,
1856 sessionTrackingIdentifier = BER_BVNULL;
1858 size_t st_len, st_pos;
1860 if ( ctrl->ldctl_iscritical ) {
1861 rs->sr_text = "sessionTracking criticality is TRUE";
1862 return LDAP_PROTOCOL_ERROR;
1865 if ( BER_BVISNULL( &ctrl->ldctl_value ) ) {
1866 rs->sr_text = "sessionTracking control value is absent";
1867 return LDAP_PROTOCOL_ERROR;
1870 if ( BER_BVISEMPTY( &ctrl->ldctl_value ) ) {
1871 rs->sr_text = "sessionTracking control value is empty";
1872 return LDAP_PROTOCOL_ERROR;
1875 /* TODO: add the capability to determine if a client is allowed
1876 * to use this control, based on identity, ip and so */
1878 ber = ber_init( &ctrl->ldctl_value );
1879 if ( ber == NULL ) {
1880 rs->sr_text = "internal error";
1884 tag = ber_skip_tag( ber, &len );
1885 if ( tag != LBER_SEQUENCE ) {
1890 /* sessionSourceIp */
1891 tag = ber_peek_tag( ber, &len );
1892 if ( tag == LBER_DEFAULT ) {
1898 tag = ber_skip_tag( ber, &len );
1900 } else if ( len > 128 ) {
1901 rs->sr_text = "sessionTracking.sessionSourceIp too long";
1902 rs->sr_err = LDAP_PROTOCOL_ERROR;
1906 tag = ber_scanf( ber, "m", &sessionSourceIp );
1909 if ( ldif_is_not_printable( sessionSourceIp.bv_val, sessionSourceIp.bv_len ) ) {
1910 BER_BVZERO( &sessionSourceIp );
1913 /* sessionSourceName */
1914 tag = ber_peek_tag( ber, &len );
1915 if ( tag == LBER_DEFAULT ) {
1921 tag = ber_skip_tag( ber, &len );
1923 } else if ( len > 65536 ) {
1924 rs->sr_text = "sessionTracking.sessionSourceName too long";
1925 rs->sr_err = LDAP_PROTOCOL_ERROR;
1929 tag = ber_scanf( ber, "m", &sessionSourceName );
1932 if ( ldif_is_not_printable( sessionSourceName.bv_val, sessionSourceName.bv_len ) ) {
1933 BER_BVZERO( &sessionSourceName );
1937 tag = ber_peek_tag( ber, &len );
1938 if ( tag == LBER_DEFAULT ) {
1944 rs->sr_text = "sessionTracking.formatOID empty";
1945 rs->sr_err = LDAP_PROTOCOL_ERROR;
1948 } else if ( len > 1024 ) {
1949 rs->sr_text = "sessionTracking.formatOID too long";
1950 rs->sr_err = LDAP_PROTOCOL_ERROR;
1954 tag = ber_scanf( ber, "m", &formatOID );
1957 rc = numericoidValidate( NULL, &formatOID );
1958 if ( rc != LDAP_SUCCESS ) {
1959 rs->sr_text = "sessionTracking.formatOID invalid";
1963 for ( i = 0; !BER_BVISNULL( &session_tracking_formats[ i ] ); i += 2 )
1965 if ( bvmatch( &formatOID, &session_tracking_formats[ i ] ) ) {
1966 formatOID = session_tracking_formats[ i + 1 ];
1971 /* sessionTrackingIdentifier */
1972 tag = ber_peek_tag( ber, &len );
1973 if ( tag == LBER_DEFAULT ) {
1979 tag = ber_skip_tag( ber, &len );
1982 /* note: should not be more than 65536... */
1983 tag = ber_scanf( ber, "m", &sessionTrackingIdentifier );
1984 if ( ldif_is_not_printable( sessionTrackingIdentifier.bv_val, sessionTrackingIdentifier.bv_len ) ) {
1985 /* we want the OID printed, at least */
1986 BER_BVSTR( &sessionTrackingIdentifier, "" );
1991 tag = ber_skip_tag( ber, &len );
1992 if ( tag != LBER_DEFAULT || len != 0 ) {
1999 if ( !BER_BVISNULL( &sessionSourceIp ) ) {
2000 st_len += STRLENOF( "IP=" ) + sessionSourceIp.bv_len;
2002 if ( !BER_BVISNULL( &sessionSourceName ) ) {
2003 if ( st_len ) st_len++;
2004 st_len += STRLENOF( "NAME=" ) + sessionSourceName.bv_len;
2006 if ( !BER_BVISNULL( &sessionTrackingIdentifier ) ) {
2007 if ( st_len ) st_len++;
2008 st_len += formatOID.bv_len + STRLENOF( "=" )
2009 + sessionTrackingIdentifier.bv_len;
2012 if ( st_len == 0 ) {
2016 st_len += STRLENOF( " []" );
2017 st_pos = strlen( op->o_log_prefix );
2019 if ( sizeof( op->o_log_prefix ) - st_pos > st_len ) {
2020 char *ptr = &op->o_log_prefix[ st_pos ];
2022 ptr = lutil_strcopy( ptr, " [" /*]*/ );
2025 if ( !BER_BVISNULL( &sessionSourceIp ) ) {
2026 ptr = lutil_strcopy( ptr, "IP=" );
2027 ptr = lutil_strcopy( ptr, sessionSourceIp.bv_val );
2031 if ( !BER_BVISNULL( &sessionSourceName ) ) {
2032 if ( st_len ) *ptr++ = ' ';
2033 ptr = lutil_strcopy( ptr, "NAME=" );
2034 ptr = lutil_strcopy( ptr, sessionSourceName.bv_val );
2038 if ( !BER_BVISNULL( &sessionTrackingIdentifier ) ) {
2039 if ( st_len ) *ptr++ = ' ';
2040 ptr = lutil_strcopy( ptr, formatOID.bv_val );
2042 ptr = lutil_strcopy( ptr, sessionTrackingIdentifier.bv_val );
2050 (void)ber_free( ber, 1 );
2052 if ( tag == LBER_ERROR ) {
2053 rs->sr_text = "sessionTracking control decoding error";
2054 return LDAP_PROTOCOL_ERROR;
2062 slap_ctrl_session_tracking_add(
2066 struct berval *name,
2070 BerElementBuffer berbuf;
2071 BerElement *ber = (BerElement *)&berbuf;
2073 static struct berval oid = BER_BVC( LDAP_CONTROL_X_SESSION_TRACKING_USERNAME );
2075 assert( ctrl != NULL );
2077 ber_init2( ber, NULL, LBER_USE_DER );
2079 ber_printf( ber, "{OOOO}", ip, name, &oid, id );
2081 if ( ber_flatten2( ber, &ctrl->ldctl_value, 0 ) == -1 ) {
2082 rs->sr_err = LDAP_OTHER;
2086 ctrl->ldctl_oid = LDAP_CONTROL_X_SESSION_TRACKING;
2087 ctrl->ldctl_iscritical = 0;
2089 rs->sr_err = LDAP_SUCCESS;
2096 slap_ctrl_session_tracking_request_add( Operation *op, SlapReply *rs, LDAPControl *ctrl )
2098 static struct berval bv_unknown = BER_BVC( SLAP_STRING_UNKNOWN );
2099 struct berval ip = BER_BVNULL,
2103 if ( !BER_BVISNULL( &op->o_conn->c_peer_name ) &&
2104 memcmp( op->o_conn->c_peer_name.bv_val, "IP=", STRLENOF( "IP=" ) ) == 0 )
2108 ip.bv_val = op->o_conn->c_peer_name.bv_val + STRLENOF( "IP=" );
2109 ip.bv_len = op->o_conn->c_peer_name.bv_len - STRLENOF( "IP=" );
2111 ptr = ber_bvchr( &ip, ':' );
2113 ip.bv_len = ptr - ip.bv_val;
2117 if ( !BER_BVISNULL( &op->o_conn->c_peer_domain ) &&
2118 !bvmatch( &op->o_conn->c_peer_domain, &bv_unknown ) )
2120 name = op->o_conn->c_peer_domain;
2123 if ( !BER_BVISNULL( &op->o_dn ) && !BER_BVISEMPTY( &op->o_dn ) ) {
2127 return slap_ctrl_session_tracking_add( op, rs, &ip, &name, &id, ctrl );
2131 #ifdef SLAP_CONTROL_X_WHATFAILED
2132 static int parseWhatFailed(
2137 if ( op->o_whatFailed != SLAP_CONTROL_NONE ) {
2138 rs->sr_text = "\"WHat Failed?\" control specified multiple times";
2139 return LDAP_PROTOCOL_ERROR;
2142 if ( !BER_BVISNULL( &ctrl->ldctl_value )) {
2143 rs->sr_text = "\"What Failed?\" control value not absent";
2144 return LDAP_PROTOCOL_ERROR;
2147 op->o_whatFailed = ctrl->ldctl_iscritical
2148 ? SLAP_CONTROL_CRITICAL
2149 : SLAP_CONTROL_NONCRITICAL;
2151 return LDAP_SUCCESS;
2155 slap_ctrl_whatFailed_add(
2160 BerElementBuffer berbuf;
2161 BerElement *ber = (BerElement *) &berbuf;
2162 LDAPControl **ctrls = NULL;
2163 struct berval ctrlval;
2164 int i, rc = LDAP_SUCCESS;
2166 ber_init2( ber, NULL, LBER_USE_DER );
2167 ber_set_option( ber, LBER_OPT_BER_MEMCTX, &op->o_tmpmemctx );
2168 ber_printf( ber, "[" /*]*/ );
2169 for ( i = 0; oids[ i ] != NULL; i++ ) {
2170 ber_printf( ber, "s", oids[ i ] );
2172 ber_printf( ber, /*[*/ "]" );
2174 if ( ber_flatten2( ber, &ctrlval, 0 ) == -1 ) {
2180 if ( rs->sr_ctrls != NULL ) {
2181 for ( ; rs->sr_ctrls[ i ] != NULL; i++ ) {
2182 if ( strcmp( rs->sr_ctrls[ i ]->ldctl_oid, LDAP_CONTROL_X_WHATFAILED ) != 0 ) {
2189 ctrls = op->o_tmprealloc( rs->sr_ctrls,
2190 sizeof(LDAPControl *)*( i + 2 )
2191 + sizeof(LDAPControl)
2192 + ctrlval.bv_len + 1,
2194 if ( ctrls == NULL ) {
2198 ctrls[ i + 1 ] = NULL;
2199 ctrls[ i ] = (LDAPControl *)&ctrls[ i + 2 ];
2200 ctrls[ i ]->ldctl_oid = LDAP_CONTROL_X_WHATFAILED;
2201 ctrls[ i ]->ldctl_iscritical = 0;
2202 ctrls[ i ]->ldctl_value.bv_val = (char *)&ctrls[ i ][ 1 ];
2203 AC_MEMCPY( ctrls[ i ]->ldctl_value.bv_val, ctrlval.bv_val, ctrlval.bv_len + 1 );
2204 ctrls[ i ]->ldctl_value.bv_len = ctrlval.bv_len;
2206 ber_free_buf( ber );
2208 rs->sr_ctrls = ctrls;
2215 #ifdef SLAP_CONTROL_X_LAZY_COMMIT
2216 static int parseLazyCommit(
2221 if ( op->o_lazyCommit != SLAP_CONTROL_NONE ) {
2222 rs->sr_text = "\"Lazy Commit?\" control specified multiple times";
2223 return LDAP_PROTOCOL_ERROR;
2226 if ( !BER_BVISNULL( &ctrl->ldctl_value )) {
2227 rs->sr_text = "\"Lazy Commit?\" control value not absent";
2228 return LDAP_PROTOCOL_ERROR;
2231 op->o_lazyCommit = ctrl->ldctl_iscritical
2232 ? SLAP_CONTROL_CRITICAL
2233 : SLAP_CONTROL_NONCRITICAL;
2235 return LDAP_SUCCESS;