2 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
4 * Copyright 1998-2005 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>
25 #include "../../libraries/liblber/lber-int.h"
27 static SLAP_CTRL_PARSE_FN parseAssert;
28 static SLAP_CTRL_PARSE_FN parsePreRead;
29 static SLAP_CTRL_PARSE_FN parsePostRead;
30 static SLAP_CTRL_PARSE_FN parseProxyAuthz;
32 static SLAP_CTRL_PARSE_FN parseDontUseCopy;
33 static SLAP_CTRL_PARSE_FN parseManageDIT;
35 static SLAP_CTRL_PARSE_FN parseManageDSAit;
36 static SLAP_CTRL_PARSE_FN parseNoOp;
37 static SLAP_CTRL_PARSE_FN parsePagedResults;
39 static SLAP_CTRL_PARSE_FN parseSortedResults;
41 static SLAP_CTRL_PARSE_FN parseValuesReturnFilter;
42 static SLAP_CTRL_PARSE_FN parsePermissiveModify;
43 static SLAP_CTRL_PARSE_FN parseDomainScope;
44 #ifdef SLAP_CONTROL_X_TREE_DELETE
45 static SLAP_CTRL_PARSE_FN parseTreeDelete;
47 static SLAP_CTRL_PARSE_FN parseSearchOptions;
48 static SLAP_CTRL_PARSE_FN parseSubentries;
50 #undef sc_mask /* avoid conflict with Irix 6.5 <sys/signal.h> */
52 const struct berval slap_pre_read_bv = BER_BVC(LDAP_CONTROL_PRE_READ);
53 const struct berval slap_post_read_bv = BER_BVC(LDAP_CONTROL_POST_READ);
55 struct slap_control_ids slap_cids;
61 /* The controlID for this control */
64 /* Operations supported by control */
67 /* Extended operations supported by control */
68 char **sc_extendedops;
70 /* Control parsing callback */
71 SLAP_CTRL_PARSE_FN *sc_parse;
73 LDAP_SLIST_ENTRY(slap_control) sc_next;
76 static LDAP_SLIST_HEAD(ControlsList, slap_control) controls_list
77 = LDAP_SLIST_HEAD_INITIALIZER(&controls_list);
80 * all known request control OIDs should be added to this list
83 * NOTE: initialize num_known_controls to 1 so that cid = 0 always
84 * addresses an undefined control; this allows to safely test for
85 * well known controls even if they are not registered, e.g. if
86 * they get moved to modules. An example is sc_LDAPsync, which
87 * is implemented in the syncprov overlay and thus, if configured
88 * as dynamic module, may not be registered. One side effect is that
89 * slap_known_controls[0] == NULL, so it should always be used
91 * FIXME: should we define the "undefined control" oid?
93 char *slap_known_controls[SLAP_MAX_CIDS+1];
94 static int num_known_controls = 1;
96 static char *proxy_authz_extops[] = {
97 LDAP_EXOP_MODIFY_PASSWD,
102 static struct slap_control control_defs[] = {
103 { LDAP_CONTROL_ASSERT,
104 (int)offsetof(struct slap_control_ids, sc_assert),
105 SLAP_CTRL_ACCESS, NULL,
106 parseAssert, LDAP_SLIST_ENTRY_INITIALIZER(next) },
107 { LDAP_CONTROL_PRE_READ,
108 (int)offsetof(struct slap_control_ids, sc_preRead),
109 SLAP_CTRL_DELETE|SLAP_CTRL_MODIFY|SLAP_CTRL_RENAME, NULL,
110 parsePreRead, LDAP_SLIST_ENTRY_INITIALIZER(next) },
111 { LDAP_CONTROL_POST_READ,
112 (int)offsetof(struct slap_control_ids, sc_postRead),
113 SLAP_CTRL_ADD|SLAP_CTRL_MODIFY|SLAP_CTRL_RENAME, NULL,
114 parsePostRead, LDAP_SLIST_ENTRY_INITIALIZER(next) },
115 { LDAP_CONTROL_VALUESRETURNFILTER,
116 (int)offsetof(struct slap_control_ids, sc_valuesReturnFilter),
117 SLAP_CTRL_GLOBAL|SLAP_CTRL_SEARCH, NULL,
118 parseValuesReturnFilter, LDAP_SLIST_ENTRY_INITIALIZER(next) },
119 { LDAP_CONTROL_PAGEDRESULTS,
120 (int)offsetof(struct slap_control_ids, sc_pagedResults),
121 SLAP_CTRL_SEARCH, NULL,
122 parsePagedResults, LDAP_SLIST_ENTRY_INITIALIZER(next) },
124 { LDAP_CONTROL_SORTREQUEST,
125 (int)offsetof(struct slap_control_ids, sc_sortedResults),
126 SLAP_CTRL_GLOBAL|SLAP_CTRL_SEARCH|SLAP_CTRL_HIDE, NULL,
127 parseSortedResults, LDAP_SLIST_ENTRY_INITIALIZER(next) },
129 { LDAP_CONTROL_X_DOMAIN_SCOPE,
130 (int)offsetof(struct slap_control_ids, sc_domainScope),
131 SLAP_CTRL_GLOBAL|SLAP_CTRL_SEARCH|SLAP_CTRL_HIDE, NULL,
132 parseDomainScope, LDAP_SLIST_ENTRY_INITIALIZER(next) },
133 { LDAP_CONTROL_X_PERMISSIVE_MODIFY,
134 (int)offsetof(struct slap_control_ids, sc_permissiveModify),
135 SLAP_CTRL_MODIFY|SLAP_CTRL_HIDE, NULL,
136 parsePermissiveModify, LDAP_SLIST_ENTRY_INITIALIZER(next) },
137 #ifdef SLAP_CONTROL_X_TREE_DELETE
138 { LDAP_CONTROL_X_TREE_DELETE,
139 (int)offsetof(struct slap_control_ids, sc_treeDelete),
140 SLAP_CTRL_DELETE|SLAP_CTRL_HIDE, NULL,
141 parseTreeDelete, LDAP_SLIST_ENTRY_INITIALIZER(next) },
143 { LDAP_CONTROL_X_SEARCH_OPTIONS,
144 (int)offsetof(struct slap_control_ids, sc_searchOptions),
145 SLAP_CTRL_GLOBAL|SLAP_CTRL_SEARCH|SLAP_CTRL_HIDE, NULL,
146 parseSearchOptions, LDAP_SLIST_ENTRY_INITIALIZER(next) },
147 { LDAP_CONTROL_SUBENTRIES,
148 (int)offsetof(struct slap_control_ids, sc_subentries),
149 SLAP_CTRL_SEARCH, NULL,
150 parseSubentries, LDAP_SLIST_ENTRY_INITIALIZER(next) },
152 (int)offsetof(struct slap_control_ids, sc_noOp),
153 SLAP_CTRL_ACCESS|SLAP_CTRL_HIDE, NULL,
154 parseNoOp, LDAP_SLIST_ENTRY_INITIALIZER(next) },
156 { LDAP_CONTROL_DONTUSECOPY,
157 (int)offsetof(struct slap_control_ids, sc_dontUseCopy),
158 SLAP_CTRL_INTROGATE|SLAP_CTRL_HIDE, NULL,
159 parseDontUseCopy, LDAP_SLIST_ENTRY_INITIALIZER(next) },
160 { LDAP_CONTROL_MANAGEDIT,
161 (int)offsetof(struct slap_control_ids, sc_manageDIT),
162 SLAP_CTRL_GLOBAL|SLAP_CTRL_UPDATE|SLAP_CTRL_HIDE, NULL,
163 parseManageDIT, LDAP_SLIST_ENTRY_INITIALIZER(next) },
165 { LDAP_CONTROL_MANAGEDSAIT,
166 (int)offsetof(struct slap_control_ids, sc_manageDSAit),
167 SLAP_CTRL_ACCESS, NULL,
168 parseManageDSAit, LDAP_SLIST_ENTRY_INITIALIZER(next) },
169 { LDAP_CONTROL_PROXY_AUTHZ,
170 (int)offsetof(struct slap_control_ids, sc_proxyAuthz),
171 SLAP_CTRL_GLOBAL|SLAP_CTRL_ACCESS, proxy_authz_extops,
172 parseProxyAuthz, LDAP_SLIST_ENTRY_INITIALIZER(next) },
173 { NULL, 0, 0, NULL, 0, LDAP_SLIST_ENTRY_INITIALIZER(next) }
177 * Register a supported control.
179 * This can be called by an OpenLDAP plugin or, indirectly, by a
180 * SLAPI plugin calling slapi_register_supported_control().
183 register_supported_control(const char *controloid,
184 slap_mask_t controlmask,
186 SLAP_CTRL_PARSE_FN *controlparsefn,
189 struct slap_control *sc;
192 if ( num_known_controls >= SLAP_MAX_CIDS ) {
193 Debug( LDAP_DEBUG_ANY, "Too many controls registered."
194 " Recompile slapd with SLAP_MAX_CIDS defined > %d\n",
195 SLAP_MAX_CIDS, 0, 0 );
199 if ( controloid == NULL ) return LDAP_PARAM_ERROR;
201 /* sanity check - should never happen */
202 for ( i = 0; slap_known_controls[ i ]; i++ ) {
203 if ( strcmp( controloid, slap_known_controls[ i ] ) == 0 ) {
204 Debug( LDAP_DEBUG_ANY,
205 "Control %s already registered.\n",
207 return LDAP_PARAM_ERROR;
211 sc = (struct slap_control *)SLAP_MALLOC( sizeof( *sc ) );
212 if ( sc == NULL ) return LDAP_NO_MEMORY;
214 sc->sc_oid = ch_strdup( controloid );
215 sc->sc_mask = controlmask;
216 if ( controlexops != NULL ) {
217 sc->sc_extendedops = ldap_charray_dup( controlexops );
218 if ( sc->sc_extendedops == NULL ) {
220 return LDAP_NO_MEMORY;
223 sc->sc_extendedops = NULL;
225 sc->sc_parse = controlparsefn;
227 if ( controlcid ) *controlcid = num_known_controls;
228 sc->sc_cid = num_known_controls;
230 /* Update slap_known_controls, too. */
231 slap_known_controls[num_known_controls-1] = sc->sc_oid;
232 slap_known_controls[num_known_controls++] = NULL;
234 LDAP_SLIST_NEXT( sc, sc_next ) = NULL;
235 LDAP_SLIST_INSERT_HEAD( &controls_list, sc, sc_next );
240 * One-time initialization of internal controls.
243 slap_controls_init( void )
249 for ( i = 0; control_defs[i].sc_oid != NULL; i++ ) {
250 int *cid = (int *)(((char *)&slap_cids) + control_defs[i].sc_cid );
251 rc = register_supported_control( control_defs[i].sc_oid,
252 control_defs[i].sc_mask, control_defs[i].sc_extendedops,
253 control_defs[i].sc_parse, cid );
254 if ( rc != LDAP_SUCCESS ) break;
261 * Free memory associated with list of supported controls.
264 controls_destroy( void )
266 struct slap_control *sc;
268 while ( !LDAP_SLIST_EMPTY(&controls_list) ) {
269 sc = LDAP_SLIST_FIRST(&controls_list);
270 LDAP_SLIST_REMOVE_HEAD(&controls_list, sc_next);
272 ch_free( sc->sc_oid );
273 if ( sc->sc_extendedops != NULL ) {
274 ldap_charray_free( sc->sc_extendedops );
281 * Format the supportedControl attribute of the root DSE,
282 * detailing which controls are supported by the directory
286 controls_root_dse_info( Entry *e )
288 AttributeDescription *ad_supportedControl
289 = slap_schema.si_ad_supportedControl;
290 struct berval vals[2];
291 struct slap_control *sc;
293 vals[1].bv_val = NULL;
296 LDAP_SLIST_FOREACH( sc, &controls_list, sc_next ) {
297 if( sc->sc_mask & SLAP_CTRL_HIDE ) continue;
299 vals[0].bv_val = sc->sc_oid;
300 vals[0].bv_len = strlen( sc->sc_oid );
302 if ( attr_merge( e, ad_supportedControl, vals, NULL ) ) {
311 * Return a list of OIDs and operation masks for supported
312 * controls. Used by SLAPI.
315 get_supported_controls(char ***ctrloidsp,
316 slap_mask_t **ctrlmasks)
321 struct slap_control *sc;
325 LDAP_SLIST_FOREACH( sc, &controls_list, sc_next ) {
335 oids = (char **)SLAP_MALLOC( (n + 1) * sizeof(char *) );
336 if ( oids == NULL ) {
337 return LDAP_NO_MEMORY;
339 masks = (slap_mask_t *)SLAP_MALLOC( (n + 1) * sizeof(slap_mask_t) );
340 if ( masks == NULL ) {
342 return LDAP_NO_MEMORY;
347 LDAP_SLIST_FOREACH( sc, &controls_list, sc_next ) {
348 oids[n] = ch_strdup( sc->sc_oid );
349 masks[n] = sc->sc_mask;
362 * Find a control given its OID.
364 static struct slap_control *
365 find_ctrl( const char *oid )
367 struct slap_control *sc;
369 LDAP_SLIST_FOREACH( sc, &controls_list, sc_next ) {
370 if ( strcmp( oid, sc->sc_oid ) == 0 ) {
379 slap_find_control_id(
383 struct slap_control *ctrl = find_ctrl( oid );
385 if ( cid ) *cid = ctrl->sc_cid;
388 return LDAP_CONTROL_NOT_FOUND;
392 slap_global_control( Operation *op, const char *oid, int *cid )
394 struct slap_control *ctrl = find_ctrl( oid );
396 if ( ctrl == NULL ) {
397 /* should not be reachable */
398 Debug( LDAP_DEBUG_ANY,
399 "slap_global_control: unrecognized control: %s\n",
401 return LDAP_CONTROL_NOT_FOUND;
404 if ( cid ) *cid = ctrl->sc_cid;
406 if ( ( ctrl->sc_mask & SLAP_CTRL_GLOBAL ) ||
407 ( ( op->o_tag & LDAP_REQ_SEARCH ) &&
408 ( ctrl->sc_mask & SLAP_CTRL_GLOBAL_SEARCH ) ) )
410 return LDAP_COMPARE_TRUE;
413 Debug( LDAP_DEBUG_TRACE,
414 "slap_global_control: unavailable control: %s\n",
417 return LDAP_COMPARE_FALSE;
420 void slap_free_ctrls(
422 LDAPControl **ctrls )
426 for (i=0; ctrls[i]; i++) {
427 op->o_tmpfree(ctrls[i], op->o_tmpmemctx );
429 op->o_tmpfree( ctrls, op->o_tmpmemctx );
435 LDAPControl *control,
438 struct slap_control *sc;
440 sc = find_ctrl( control->ldctl_oid );
442 /* recognized control */
444 switch( op->o_tag ) {
446 tagmask = SLAP_CTRL_ADD;
449 tagmask = SLAP_CTRL_BIND;
451 case LDAP_REQ_COMPARE:
452 tagmask = SLAP_CTRL_COMPARE;
454 case LDAP_REQ_DELETE:
455 tagmask = SLAP_CTRL_DELETE;
457 case LDAP_REQ_MODIFY:
458 tagmask = SLAP_CTRL_MODIFY;
460 case LDAP_REQ_RENAME:
461 tagmask = SLAP_CTRL_RENAME;
463 case LDAP_REQ_SEARCH:
464 tagmask = SLAP_CTRL_SEARCH;
466 case LDAP_REQ_UNBIND:
467 tagmask = SLAP_CTRL_UNBIND;
469 case LDAP_REQ_ABANDON:
470 tagmask = SLAP_CTRL_ABANDON;
472 case LDAP_REQ_EXTENDED:
474 assert( op->ore_reqoid.bv_val != NULL );
475 if( sc->sc_extendedops != NULL ) {
477 for( i=0; sc->sc_extendedops[i] != NULL; i++ ) {
478 if( strcmp( op->ore_reqoid.bv_val,
479 sc->sc_extendedops[i] ) == 0 )
488 *text = "controls internal error";
492 if (( sc->sc_mask & tagmask ) == tagmask ) {
493 /* available extension */
496 if( !sc->sc_parse ) {
497 *text = "not yet implemented";
501 rc = sc->sc_parse( op, rs, control );
503 assert( rc != LDAP_UNAVAILABLE_CRITICAL_EXTENSION );
507 } else if( control->ldctl_iscritical ) {
508 /* unavailable CRITICAL control */
509 *text = "critical extension is unavailable";
510 return LDAP_UNAVAILABLE_CRITICAL_EXTENSION;
512 } else if( control->ldctl_iscritical ) {
513 /* unrecognized CRITICAL control */
514 *text = "critical extension is not recognized";
515 return LDAP_UNAVAILABLE_CRITICAL_EXTENSION;
530 BerElement *ber = op->o_ber;
533 len = ber_pvt_ber_remaining(ber);
537 rs->sr_err = LDAP_SUCCESS;
541 if(( tag = ber_peek_tag( ber, &len )) != LDAP_TAG_CONTROLS ) {
542 if( tag == LBER_ERROR ) {
543 rs->sr_err = SLAPD_DISCONNECT;
544 rs->sr_text = "unexpected data in PDU";
550 Debug( LDAP_DEBUG_TRACE,
551 "=> get_ctrls\n", 0, 0, 0 );
553 if( op->o_protocol < LDAP_VERSION3 ) {
554 rs->sr_err = SLAPD_DISCONNECT;
555 rs->sr_text = "controls require LDAPv3";
559 /* one for first control, one for termination */
560 op->o_ctrls = op->o_tmpalloc( 2 * sizeof(LDAPControl *), op->o_tmpmemctx );
563 if( op->ctrls == NULL ) {
564 rs->sr_err = LDAP_NO_MEMORY;
565 rs->sr_text = "no memory";
570 op->o_ctrls[nctrls] = NULL;
572 /* step through each element */
573 for( tag = ber_first_element( ber, &len, &opaque );
575 tag = ber_next_element( ber, &len, opaque ) )
578 LDAPControl **tctrls;
580 c = op->o_tmpalloc( sizeof(LDAPControl), op->o_tmpmemctx );
581 memset(c, 0, sizeof(LDAPControl));
583 /* allocate pointer space for current controls (nctrls)
584 * + this control + extra NULL
586 tctrls = op->o_tmprealloc( op->o_ctrls,
587 (nctrls+2) * sizeof(LDAPControl *), op->o_tmpmemctx );
590 if( tctrls == NULL ) {
592 ldap_controls_free(op->o_ctrls);
595 rs->sr_err = LDAP_NO_MEMORY;
596 rs->sr_text = "no memory";
600 op->o_ctrls = tctrls;
602 op->o_ctrls[nctrls++] = c;
603 op->o_ctrls[nctrls] = NULL;
605 tag = ber_scanf( ber, "{m" /*}*/, &bv );
606 c->ldctl_oid = bv.bv_val;
608 if( tag == LBER_ERROR ) {
609 Debug( LDAP_DEBUG_TRACE, "=> get_ctrls: get oid failed.\n",
612 slap_free_ctrls( op, op->o_ctrls );
614 rs->sr_err = SLAPD_DISCONNECT;
615 rs->sr_text = "decoding controls error";
618 } else if( c->ldctl_oid == NULL ) {
619 Debug( LDAP_DEBUG_TRACE,
620 "get_ctrls: conn %lu got emtpy OID.\n",
621 op->o_connid, 0, 0 );
623 slap_free_ctrls( op, op->o_ctrls );
625 rs->sr_err = LDAP_PROTOCOL_ERROR;
626 rs->sr_text = "OID field is empty";
630 tag = ber_peek_tag( ber, &len );
632 if( tag == LBER_BOOLEAN ) {
634 tag = ber_scanf( ber, "b", &crit );
636 if( tag == LBER_ERROR ) {
637 Debug( LDAP_DEBUG_TRACE, "=> get_ctrls: get crit failed.\n",
639 slap_free_ctrls( op, op->o_ctrls );
641 rs->sr_err = SLAPD_DISCONNECT;
642 rs->sr_text = "decoding controls error";
646 c->ldctl_iscritical = (crit != 0);
647 tag = ber_peek_tag( ber, &len );
650 if( tag == LBER_OCTETSTRING ) {
651 tag = ber_scanf( ber, "m", &c->ldctl_value );
653 if( tag == LBER_ERROR ) {
654 Debug( LDAP_DEBUG_TRACE, "=> get_ctrls: conn %lu: "
655 "%s (%scritical): get value failed.\n",
656 op->o_connid, c->ldctl_oid,
657 c->ldctl_iscritical ? "" : "non" );
658 slap_free_ctrls( op, op->o_ctrls );
660 rs->sr_err = SLAPD_DISCONNECT;
661 rs->sr_text = "decoding controls error";
666 Debug( LDAP_DEBUG_TRACE,
667 "=> get_ctrls: oid=\"%s\" (%scritical)\n",
668 c->ldctl_oid, c->ldctl_iscritical ? "" : "non", 0 );
670 rs->sr_err = slap_parse_ctrl( op, rs, c, &rs->sr_text );
671 if ( rs->sr_err != LDAP_SUCCESS ) {
677 Debug( LDAP_DEBUG_TRACE,
678 "<= get_ctrls: n=%d rc=%d err=\"%s\"\n",
679 nctrls, rs->sr_err, rs->sr_text ? rs->sr_text : "");
681 if( sendres && rs->sr_err != LDAP_SUCCESS ) {
682 if( rs->sr_err == SLAPD_DISCONNECT ) {
683 rs->sr_err = LDAP_PROTOCOL_ERROR;
684 send_ldap_disconnect( op, rs );
685 rs->sr_err = SLAPD_DISCONNECT;
687 send_ldap_result( op, rs );
699 BI_chk_controls fnc )
703 switch ( op->o_ctrlflag[ ctrl ] ) {
704 case SLAP_CONTROL_NONCRITICAL:
705 for ( i = 0, j = -1; op->o_ctrls[ i ] != NULL; i++ ) {
706 if ( strcmp( op->o_ctrls[ i ]->ldctl_oid,
707 slap_known_controls[ ctrl - 1 ] ) == 0 )
714 rs->sr_err = LDAP_OTHER;
722 op->o_tmpfree( op->o_ctrls[ j ], op->o_tmpmemctx );
725 AC_MEMCPY( &op->o_ctrls[ j ], &op->o_ctrls[ j + 1 ],
726 ( i - j ) * sizeof( LDAPControl * ) );
729 op->o_tmpfree( op->o_ctrls, op->o_tmpmemctx );
733 op->o_ctrlflag[ ctrl ] = SLAP_CONTROL_IGNORED;
735 Debug( LDAP_DEBUG_ANY, "%s: "
736 "non-critical control \"%s\" not supported; stripped.\n",
737 op->o_log_prefix, slap_known_controls[ ctrl ], 0 );
740 case SLAP_CONTROL_IGNORED:
741 case SLAP_CONTROL_NONE:
742 rs->sr_err = SLAP_CB_CONTINUE;
745 case SLAP_CONTROL_CRITICAL:
746 rs->sr_err = LDAP_UNAVAILABLE_CRITICAL_EXTENSION;
750 Debug( LDAP_DEBUG_ANY, "%s: "
751 "critical control \"%s\" not supported.\n",
752 op->o_log_prefix, slap_known_controls[ ctrl ], 0 );
756 /* handle all cases! */
764 static int parseDontUseCopy (
769 if ( op->o_dontUseCopy != SLAP_CONTROL_NONE ) {
770 rs->sr_text = "dontUseCopy control specified multiple times";
771 return LDAP_PROTOCOL_ERROR;
774 if ( ctrl->ldctl_value.bv_len ) {
775 rs->sr_text = "dontUseCopy control value not empty";
776 return LDAP_PROTOCOL_ERROR;
779 if ( ctrl->ldctl_iscritical != SLAP_CONTROL_CRITICAL ) {
780 rs->sr_text = "dontUseCopy criticality of FALSE not allowed";
781 return LDAP_PROTOCOL_ERROR;
784 op->o_dontUseCopy = SLAP_CONTROL_CRITICAL;
788 static int parseManageDIT (
793 if ( op->o_managedit != SLAP_CONTROL_NONE ) {
794 rs->sr_text = "manageDIT control specified multiple times";
795 return LDAP_PROTOCOL_ERROR;
798 if ( ctrl->ldctl_value.bv_len ) {
799 rs->sr_text = "manageDIT control value not empty";
800 return LDAP_PROTOCOL_ERROR;
803 op->o_managedit = ctrl->ldctl_iscritical
804 ? SLAP_CONTROL_CRITICAL
805 : SLAP_CONTROL_NONCRITICAL;
811 static int parseManageDSAit (
816 if ( op->o_managedsait != SLAP_CONTROL_NONE ) {
817 rs->sr_text = "manageDSAit control specified multiple times";
818 return LDAP_PROTOCOL_ERROR;
821 if ( ctrl->ldctl_value.bv_len ) {
822 rs->sr_text = "manageDSAit control value not empty";
823 return LDAP_PROTOCOL_ERROR;
826 op->o_managedsait = ctrl->ldctl_iscritical
827 ? SLAP_CONTROL_CRITICAL
828 : SLAP_CONTROL_NONCRITICAL;
833 static int parseProxyAuthz (
839 struct berval dn = BER_BVNULL;
841 if ( op->o_proxy_authz != SLAP_CONTROL_NONE ) {
842 rs->sr_text = "proxy authorization control specified multiple times";
843 return LDAP_PROTOCOL_ERROR;
846 op->o_proxy_authz = ctrl->ldctl_iscritical
847 ? SLAP_CONTROL_CRITICAL
848 : SLAP_CONTROL_NONCRITICAL;
850 Debug( LDAP_DEBUG_ARGS,
851 "parseProxyAuthz: conn %lu authzid=\"%s\"\n",
853 ctrl->ldctl_value.bv_len ? ctrl->ldctl_value.bv_val : "anonymous",
856 if ( ctrl->ldctl_value.bv_len == 0 ) {
857 Debug( LDAP_DEBUG_TRACE,
858 "parseProxyAuthz: conn=%lu anonymous\n",
859 op->o_connid, 0, 0 );
862 op->o_ndn.bv_val[ 0 ] = '\0';
863 op->o_ndn.bv_len = 0;
865 op->o_dn.bv_val[ 0 ] = '\0';
871 rc = slap_sasl_getdn( op->o_conn, op, &ctrl->ldctl_value,
872 NULL, &dn, SLAP_GETDN_AUTHZID );
874 /* FIXME: empty DN in proxyAuthz control should be legal... */
875 if( rc != LDAP_SUCCESS /* || !dn.bv_len */ ) {
877 ch_free( dn.bv_val );
879 rs->sr_text = "authzId mapping failed";
880 return LDAP_PROXY_AUTHZ_FAILURE;
883 Debug( LDAP_DEBUG_TRACE,
884 "parseProxyAuthz: conn=%lu \"%s\"\n",
886 dn.bv_len ? dn.bv_val : "(NULL)", 0 );
888 rc = slap_sasl_authorized( op, &op->o_ndn, &dn );
891 ch_free( dn.bv_val );
892 rs->sr_text = "not authorized to assume identity";
893 return LDAP_PROXY_AUTHZ_FAILURE;
896 ch_free( op->o_ndn.bv_val );
897 ch_free( op->o_dn.bv_val );
900 * NOTE: since slap_sasl_getdn() returns a normalized dn,
901 * from now on op->o_dn is normalized
904 ber_dupbv( &op->o_dn, &dn );
907 Statslog( LDAP_DEBUG_STATS, "%s PROXYAUTHZ dn=\"%s\"\n",
908 op->o_log_prefix, dn.bv_val, 0, 0, 0 );
913 static int parseNoOp (
918 if ( op->o_noop != SLAP_CONTROL_NONE ) {
919 rs->sr_text = "noop control specified multiple times";
920 return LDAP_PROTOCOL_ERROR;
923 if ( ctrl->ldctl_value.bv_len ) {
924 rs->sr_text = "noop control value not empty";
925 return LDAP_PROTOCOL_ERROR;
928 op->o_noop = ctrl->ldctl_iscritical
929 ? SLAP_CONTROL_CRITICAL
930 : SLAP_CONTROL_NONCRITICAL;
935 static int parsePagedResults (
940 int rc = LDAP_SUCCESS;
944 struct berval cookie = BER_BVNULL;
945 PagedResultsState *ps;
947 if ( op->o_pagedresults != SLAP_CONTROL_NONE ) {
948 rs->sr_text = "paged results control specified multiple times";
949 return LDAP_PROTOCOL_ERROR;
952 if ( BER_BVISEMPTY( &ctrl->ldctl_value ) ) {
953 rs->sr_text = "paged results control value is empty (or absent)";
954 return LDAP_PROTOCOL_ERROR;
957 /* Parse the control value
958 * realSearchControlValue ::= SEQUENCE {
959 * size INTEGER (0..maxInt),
960 * -- requested page size from client
961 * -- result set size estimate from server
962 * cookie OCTET STRING
965 ber = ber_init( &ctrl->ldctl_value );
967 rs->sr_text = "internal error";
971 tag = ber_scanf( ber, "{im}", &size, &cookie );
973 if ( tag == LBER_ERROR ) {
974 rs->sr_text = "paged results control could not be decoded";
975 rc = LDAP_PROTOCOL_ERROR;
980 rs->sr_text = "paged results control size invalid";
981 rc = LDAP_PROTOCOL_ERROR;
985 ps = op->o_tmpalloc( sizeof(PagedResultsState), op->o_tmpmemctx );
986 *ps = op->o_conn->c_pagedresults_state;
988 op->o_pagedresults_state = ps;
990 /* NOTE: according to RFC 2696 3.:
992 If the page size is greater than or equal to the sizeLimit value, the
993 server should ignore the control as the request can be satisfied in a
996 * NOTE: this assumes that the op->ors_slimit be set
997 * before the controls are parsed.
1000 if ( op->ors_slimit > 0 && size >= op->ors_slimit ) {
1001 op->o_pagedresults = SLAP_CONTROL_IGNORED;
1003 } else if ( ctrl->ldctl_iscritical ) {
1004 op->o_pagedresults = SLAP_CONTROL_CRITICAL;
1007 op->o_pagedresults = SLAP_CONTROL_NONCRITICAL;
1011 (void)ber_free( ber, 1 );
1016 static int parseSortedResults (
1021 int rc = LDAP_SUCCESS;
1023 if ( op->o_sortedresults != SLAP_CONTROL_NONE ) {
1024 rs->sr_text = "sorted results control specified multiple times";
1025 return LDAP_PROTOCOL_ERROR;
1028 if ( BER_BVISEMPTY( &ctrl->ldctl_value ) ) {
1029 rs->sr_text = "sorted results control value is empty (or absent)";
1030 return LDAP_PROTOCOL_ERROR;
1033 /* blow off parsing the value */
1035 op->o_sortedresults = ctrl->ldctl_iscritical
1036 ? SLAP_CONTROL_CRITICAL
1037 : SLAP_CONTROL_NONCRITICAL;
1043 static int parseAssert (
1049 struct berval fstr = BER_BVNULL;
1051 if ( op->o_assert != SLAP_CONTROL_NONE ) {
1052 rs->sr_text = "assert control specified multiple times";
1053 return LDAP_PROTOCOL_ERROR;
1056 if ( ctrl->ldctl_value.bv_len == 0 ) {
1057 rs->sr_text = "assert control value is empty (or absent)";
1058 return LDAP_PROTOCOL_ERROR;
1061 ber = ber_init( &(ctrl->ldctl_value) );
1063 rs->sr_text = "assert control: internal error";
1067 rs->sr_err = get_filter( op, ber, (Filter **)&(op->o_assertion),
1069 if( rs->sr_err != LDAP_SUCCESS ) {
1070 if( rs->sr_err == SLAPD_DISCONNECT ) {
1071 rs->sr_err = LDAP_PROTOCOL_ERROR;
1072 send_ldap_disconnect( op, rs );
1073 rs->sr_err = SLAPD_DISCONNECT;
1075 send_ldap_result( op, rs );
1077 if( op->o_assertion != NULL ) {
1078 filter_free_x( op, op->o_assertion );
1084 filter2bv_x( op, op->o_assertion, &fstr );
1086 Debug( LDAP_DEBUG_ARGS, "parseAssert: conn %ld assert: %s\n",
1087 op->o_connid, fstr.bv_len ? fstr.bv_val : "empty" , 0 );
1088 op->o_tmpfree( fstr.bv_val, op->o_tmpmemctx );
1091 op->o_assert = ctrl->ldctl_iscritical
1092 ? SLAP_CONTROL_CRITICAL
1093 : SLAP_CONTROL_NONCRITICAL;
1095 rs->sr_err = LDAP_SUCCESS;
1096 return LDAP_SUCCESS;
1099 static int parsePreRead (
1104 ber_len_t siz, off, i;
1105 AttributeName *an = NULL;
1108 if ( op->o_preread != SLAP_CONTROL_NONE ) {
1109 rs->sr_text = "preread control specified multiple times";
1110 return LDAP_PROTOCOL_ERROR;
1113 if ( ctrl->ldctl_value.bv_len == 0 ) {
1114 rs->sr_text = "preread control value is empty (or absent)";
1115 return LDAP_PROTOCOL_ERROR;
1118 ber = ber_init( &(ctrl->ldctl_value) );
1120 rs->sr_text = "preread control: internal error";
1124 siz = sizeof( AttributeName );
1125 off = offsetof( AttributeName, an_name );
1126 if ( ber_scanf( ber, "{M}", &an, &siz, off ) == LBER_ERROR ) {
1127 rs->sr_text = "preread control: decoding error";
1128 return LDAP_PROTOCOL_ERROR;
1131 for( i=0; i<siz; i++ ) {
1132 int rc = LDAP_SUCCESS;
1133 const char *dummy = NULL;
1135 an[i].an_desc = NULL;
1137 an[i].an_oc_exclude = 0;
1138 rc = slap_bv2ad( &an[i].an_name, &an[i].an_desc, &dummy );
1139 if ( rc != LDAP_SUCCESS && ctrl->ldctl_iscritical ) {
1142 : "postread control: unknown attributeType";
1147 op->o_preread = ctrl->ldctl_iscritical
1148 ? SLAP_CONTROL_CRITICAL
1149 : SLAP_CONTROL_NONCRITICAL;
1151 op->o_preread_attrs = an;
1153 rs->sr_err = LDAP_SUCCESS;
1154 return LDAP_SUCCESS;
1157 static int parsePostRead (
1162 ber_len_t siz, off, i;
1163 AttributeName *an = NULL;
1166 if ( op->o_postread != SLAP_CONTROL_NONE ) {
1167 rs->sr_text = "postread control specified multiple times";
1168 return LDAP_PROTOCOL_ERROR;
1171 if ( ctrl->ldctl_value.bv_len == 0 ) {
1172 rs->sr_text = "postread control value is empty (or absent)";
1173 return LDAP_PROTOCOL_ERROR;
1176 ber = ber_init( &(ctrl->ldctl_value) );
1178 rs->sr_text = "postread control: internal error";
1182 siz = sizeof( AttributeName );
1183 off = offsetof( AttributeName, an_name );
1184 if ( ber_scanf( ber, "{M}", &an, &siz, off ) == LBER_ERROR ) {
1185 rs->sr_text = "postread control: decoding error";
1186 return LDAP_PROTOCOL_ERROR;
1189 for( i=0; i<siz; i++ ) {
1190 int rc = LDAP_SUCCESS;
1191 const char *dummy = NULL;
1193 an[i].an_desc = NULL;
1195 an[i].an_oc_exclude = 0;
1196 rc = slap_bv2ad( &an[i].an_name, &an[i].an_desc, &dummy );
1197 if ( rc != LDAP_SUCCESS && ctrl->ldctl_iscritical ) {
1200 : "postread control: unknown attributeType";
1205 op->o_postread = ctrl->ldctl_iscritical
1206 ? SLAP_CONTROL_CRITICAL
1207 : SLAP_CONTROL_NONCRITICAL;
1209 op->o_postread_attrs = an;
1211 rs->sr_err = LDAP_SUCCESS;
1212 return LDAP_SUCCESS;
1215 static int parseValuesReturnFilter (
1221 struct berval fstr = BER_BVNULL;
1223 if ( op->o_valuesreturnfilter != SLAP_CONTROL_NONE ) {
1224 rs->sr_text = "valuesReturnFilter control specified multiple times";
1225 return LDAP_PROTOCOL_ERROR;
1228 if ( ctrl->ldctl_value.bv_len == 0 ) {
1229 rs->sr_text = "valuesReturnFilter control value is empty (or absent)";
1230 return LDAP_PROTOCOL_ERROR;
1233 ber = ber_init( &(ctrl->ldctl_value) );
1235 rs->sr_text = "internal error";
1239 rs->sr_err = get_vrFilter( op, ber,
1240 (ValuesReturnFilter **)&(op->o_vrFilter), &rs->sr_text);
1242 if( rs->sr_err != LDAP_SUCCESS ) {
1243 if( rs->sr_err == SLAPD_DISCONNECT ) {
1244 rs->sr_err = LDAP_PROTOCOL_ERROR;
1245 send_ldap_disconnect( op, rs );
1246 rs->sr_err = SLAPD_DISCONNECT;
1248 send_ldap_result( op, rs );
1250 if( op->o_vrFilter != NULL) vrFilter_free( op, op->o_vrFilter );
1254 vrFilter2bv( op, op->o_vrFilter, &fstr );
1257 Debug( LDAP_DEBUG_ARGS, " vrFilter: %s\n",
1258 fstr.bv_len ? fstr.bv_val : "empty", 0, 0 );
1259 op->o_tmpfree( fstr.bv_val, op->o_tmpmemctx );
1262 op->o_valuesreturnfilter = ctrl->ldctl_iscritical
1263 ? SLAP_CONTROL_CRITICAL
1264 : SLAP_CONTROL_NONCRITICAL;
1266 rs->sr_err = LDAP_SUCCESS;
1267 return LDAP_SUCCESS;
1270 static int parseSubentries (
1275 if ( op->o_subentries != SLAP_CONTROL_NONE ) {
1276 rs->sr_text = "subentries control specified multiple times";
1277 return LDAP_PROTOCOL_ERROR;
1280 /* FIXME: should use BER library */
1281 if( ( ctrl->ldctl_value.bv_len != 3 )
1282 || ( ctrl->ldctl_value.bv_val[0] != 0x01 )
1283 || ( ctrl->ldctl_value.bv_val[1] != 0x01 ))
1285 rs->sr_text = "subentries control value encoding is bogus";
1286 return LDAP_PROTOCOL_ERROR;
1289 op->o_subentries = ctrl->ldctl_iscritical
1290 ? SLAP_CONTROL_CRITICAL
1291 : SLAP_CONTROL_NONCRITICAL;
1293 if (ctrl->ldctl_value.bv_val[2]) {
1294 set_subentries_visibility( op );
1297 return LDAP_SUCCESS;
1300 static int parsePermissiveModify (
1305 if ( op->o_permissive_modify != SLAP_CONTROL_NONE ) {
1306 rs->sr_text = "permissiveModify control specified multiple times";
1307 return LDAP_PROTOCOL_ERROR;
1310 if ( ctrl->ldctl_value.bv_len ) {
1311 rs->sr_text = "permissiveModify control value not empty";
1312 return LDAP_PROTOCOL_ERROR;
1315 op->o_permissive_modify = ctrl->ldctl_iscritical
1316 ? SLAP_CONTROL_CRITICAL
1317 : SLAP_CONTROL_NONCRITICAL;
1319 return LDAP_SUCCESS;
1322 static int parseDomainScope (
1327 if ( op->o_domain_scope != SLAP_CONTROL_NONE ) {
1328 rs->sr_text = "domainScope control specified multiple times";
1329 return LDAP_PROTOCOL_ERROR;
1332 if ( ctrl->ldctl_value.bv_len ) {
1333 rs->sr_text = "domainScope control value not empty";
1334 return LDAP_PROTOCOL_ERROR;
1337 op->o_domain_scope = ctrl->ldctl_iscritical
1338 ? SLAP_CONTROL_CRITICAL
1339 : SLAP_CONTROL_NONCRITICAL;
1341 return LDAP_SUCCESS;
1344 #ifdef SLAP_CONTROL_X_TREE_DELETE
1345 static int parseTreeDelete (
1350 if ( op->o_tree_delete != SLAP_CONTROL_NONE ) {
1351 rs->sr_text = "treeDelete control specified multiple times";
1352 return LDAP_PROTOCOL_ERROR;
1355 if ( ctrl->ldctl_value.bv_len ) {
1356 rs->sr_text = "treeDelete control value not empty";
1357 return LDAP_PROTOCOL_ERROR;
1360 op->o_tree_delete = ctrl->ldctl_iscritical
1361 ? SLAP_CONTROL_CRITICAL
1362 : SLAP_CONTROL_NONCRITICAL;
1364 return LDAP_SUCCESS;
1368 static int parseSearchOptions (
1374 ber_int_t search_flags;
1377 if ( ctrl->ldctl_value.bv_len == 0 ) {
1378 rs->sr_text = "searchOptions control value is empty (or absent)";
1379 return LDAP_PROTOCOL_ERROR;
1382 ber = ber_init( &ctrl->ldctl_value );
1384 rs->sr_text = "internal error";
1388 if ( (tag = ber_scanf( ber, "{i}", &search_flags )) == LBER_ERROR ) {
1389 rs->sr_text = "searchOptions control decoding error";
1390 return LDAP_PROTOCOL_ERROR;
1393 (void) ber_free( ber, 1 );
1395 if ( search_flags & LDAP_SEARCH_FLAG_DOMAIN_SCOPE ) {
1396 if ( op->o_domain_scope != SLAP_CONTROL_NONE ) {
1397 rs->sr_text = "searchOptions control specified multiple times "
1398 "or with domainScope control";
1399 return LDAP_PROTOCOL_ERROR;
1402 op->o_domain_scope = ctrl->ldctl_iscritical
1403 ? SLAP_CONTROL_CRITICAL
1404 : SLAP_CONTROL_NONCRITICAL;
1407 if ( search_flags & ~(LDAP_SEARCH_FLAG_DOMAIN_SCOPE) ) {
1408 /* Other search flags not recognised so far,
1410 * LDAP_SEARCH_FLAG_PHANTOM_ROOM
1412 rs->sr_text = "searchOptions contained unrecognized flag";
1413 return LDAP_UNWILLING_TO_PERFORM;
1416 return LDAP_SUCCESS;