2 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
4 * Copyright 1998-2007 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>
26 #include "../../libraries/liblber/lber-int.h"
28 static SLAP_CTRL_PARSE_FN parseAssert;
29 static SLAP_CTRL_PARSE_FN parseDomainScope;
30 static SLAP_CTRL_PARSE_FN parseDontUseCopy;
31 static SLAP_CTRL_PARSE_FN parseManageDSAit;
32 static SLAP_CTRL_PARSE_FN parseNoOp;
33 static SLAP_CTRL_PARSE_FN parsePagedResults;
34 static SLAP_CTRL_PARSE_FN parsePermissiveModify;
35 static SLAP_CTRL_PARSE_FN parsePreRead, parsePostRead;
36 static SLAP_CTRL_PARSE_FN parseProxyAuthz;
37 static SLAP_CTRL_PARSE_FN parseRelax;
38 static SLAP_CTRL_PARSE_FN parseSearchOptions;
39 #ifdef SLAP_CONTROL_X_SORTEDRESULTS
40 static SLAP_CTRL_PARSE_FN parseSortedResults;
42 static SLAP_CTRL_PARSE_FN parseSubentries;
43 #ifdef SLAP_CONTROL_X_TREE_DELETE
44 static SLAP_CTRL_PARSE_FN parseTreeDelete;
46 static SLAP_CTRL_PARSE_FN parseValuesReturnFilter;
47 #ifdef SLAP_CONTROL_X_SESSION_TRACKING
48 static SLAP_CTRL_PARSE_FN parseSessionTracking;
51 #undef sc_mask /* avoid conflict with Irix 6.5 <sys/signal.h> */
53 const struct berval slap_pre_read_bv = BER_BVC(LDAP_CONTROL_PRE_READ);
54 const struct berval slap_post_read_bv = BER_BVC(LDAP_CONTROL_POST_READ);
56 struct slap_control_ids slap_cids;
62 /* The controlID for this control */
65 /* Operations supported by control */
68 /* Extended operations supported by control */
69 char **sc_extendedops; /* input */
70 BerVarray sc_extendedopsbv; /* run-time use */
72 /* Control parsing callback */
73 SLAP_CTRL_PARSE_FN *sc_parse;
75 LDAP_SLIST_ENTRY(slap_control) sc_next;
78 static LDAP_SLIST_HEAD(ControlsList, slap_control) controls_list
79 = LDAP_SLIST_HEAD_INITIALIZER(&controls_list);
82 * all known request control OIDs should be added to this list
85 * NOTE: initialize num_known_controls to 1 so that cid = 0 always
86 * addresses an undefined control; this allows to safely test for
87 * well known controls even if they are not registered, e.g. if
88 * they get moved to modules. An example is sc_LDAPsync, which
89 * is implemented in the syncprov overlay and thus, if configured
90 * as dynamic module, may not be registered. One side effect is that
91 * slap_known_controls[0] == NULL, so it should always be used
93 * FIXME: should we define the "undefined control" oid?
95 char *slap_known_controls[SLAP_MAX_CIDS+1];
96 static int num_known_controls = 1;
98 static char *proxy_authz_extops[] = {
99 LDAP_EXOP_MODIFY_PASSWD,
105 static char *manageDSAit_extops[] = {
110 #ifdef SLAP_CONTROL_X_SESSION_TRACKING
111 static char *session_tracking_extops[] = {
112 LDAP_EXOP_MODIFY_PASSWD,
119 static struct slap_control control_defs[] = {
120 { LDAP_CONTROL_ASSERT,
121 (int)offsetof(struct slap_control_ids, sc_assert),
122 SLAP_CTRL_DELETE|SLAP_CTRL_MODIFY|SLAP_CTRL_RENAME|
123 SLAP_CTRL_COMPARE|SLAP_CTRL_SEARCH,
125 parseAssert, LDAP_SLIST_ENTRY_INITIALIZER(next) },
126 { LDAP_CONTROL_PRE_READ,
127 (int)offsetof(struct slap_control_ids, sc_preRead),
128 SLAP_CTRL_DELETE|SLAP_CTRL_MODIFY|SLAP_CTRL_RENAME,
130 parsePreRead, LDAP_SLIST_ENTRY_INITIALIZER(next) },
131 { LDAP_CONTROL_POST_READ,
132 (int)offsetof(struct slap_control_ids, sc_postRead),
133 SLAP_CTRL_ADD|SLAP_CTRL_MODIFY|SLAP_CTRL_RENAME,
135 parsePostRead, LDAP_SLIST_ENTRY_INITIALIZER(next) },
136 { LDAP_CONTROL_VALUESRETURNFILTER,
137 (int)offsetof(struct slap_control_ids, sc_valuesReturnFilter),
138 SLAP_CTRL_GLOBAL|SLAP_CTRL_SEARCH,
140 parseValuesReturnFilter, LDAP_SLIST_ENTRY_INITIALIZER(next) },
141 { LDAP_CONTROL_PAGEDRESULTS,
142 (int)offsetof(struct slap_control_ids, sc_pagedResults),
145 parsePagedResults, LDAP_SLIST_ENTRY_INITIALIZER(next) },
146 #ifdef SLAP_CONTROL_X_SORTEDRESULTS
147 { LDAP_CONTROL_SORTREQUEST,
148 (int)offsetof(struct slap_control_ids, sc_sortedResults),
149 SLAP_CTRL_GLOBAL|SLAP_CTRL_SEARCH|SLAP_CTRL_HIDE,
151 parseSortedResults, LDAP_SLIST_ENTRY_INITIALIZER(next) },
153 { LDAP_CONTROL_X_DOMAIN_SCOPE,
154 (int)offsetof(struct slap_control_ids, sc_domainScope),
155 SLAP_CTRL_GLOBAL|SLAP_CTRL_SEARCH|SLAP_CTRL_HIDE,
157 parseDomainScope, LDAP_SLIST_ENTRY_INITIALIZER(next) },
158 { LDAP_CONTROL_DONTUSECOPY,
159 (int)offsetof(struct slap_control_ids, sc_dontUseCopy),
160 SLAP_CTRL_GLOBAL|SLAP_CTRL_INTROGATE|SLAP_CTRL_HIDE,
162 parseDontUseCopy, LDAP_SLIST_ENTRY_INITIALIZER(next) },
163 { LDAP_CONTROL_X_PERMISSIVE_MODIFY,
164 (int)offsetof(struct slap_control_ids, sc_permissiveModify),
165 SLAP_CTRL_MODIFY|SLAP_CTRL_HIDE,
167 parsePermissiveModify, LDAP_SLIST_ENTRY_INITIALIZER(next) },
168 #ifdef SLAP_CONTROL_X_TREE_DELETE
169 { LDAP_CONTROL_X_TREE_DELETE,
170 (int)offsetof(struct slap_control_ids, sc_treeDelete),
171 SLAP_CTRL_DELETE|SLAP_CTRL_HIDE,
173 parseTreeDelete, LDAP_SLIST_ENTRY_INITIALIZER(next) },
175 { LDAP_CONTROL_X_SEARCH_OPTIONS,
176 (int)offsetof(struct slap_control_ids, sc_searchOptions),
177 SLAP_CTRL_GLOBAL|SLAP_CTRL_SEARCH|SLAP_CTRL_HIDE,
179 parseSearchOptions, LDAP_SLIST_ENTRY_INITIALIZER(next) },
180 { LDAP_CONTROL_SUBENTRIES,
181 (int)offsetof(struct slap_control_ids, sc_subentries),
184 parseSubentries, LDAP_SLIST_ENTRY_INITIALIZER(next) },
186 (int)offsetof(struct slap_control_ids, sc_noOp),
187 SLAP_CTRL_ACCESS|SLAP_CTRL_HIDE,
189 parseNoOp, LDAP_SLIST_ENTRY_INITIALIZER(next) },
190 { LDAP_CONTROL_RELAX,
191 (int)offsetof(struct slap_control_ids, sc_relax),
192 SLAP_CTRL_GLOBAL|SLAP_CTRL_UPDATE|SLAP_CTRL_HIDE,
194 parseRelax, LDAP_SLIST_ENTRY_INITIALIZER(next) },
196 { LDAP_CONTROL_X_TXN_SPEC,
197 (int)offsetof(struct slap_control_ids, sc_txnSpec),
198 SLAP_CTRL_UPDATE|SLAP_CTRL_HIDE,
200 txn_spec_ctrl, LDAP_SLIST_ENTRY_INITIALIZER(next) },
202 { LDAP_CONTROL_MANAGEDSAIT,
203 (int)offsetof(struct slap_control_ids, sc_manageDSAit),
205 manageDSAit_extops, NULL,
206 parseManageDSAit, LDAP_SLIST_ENTRY_INITIALIZER(next) },
207 { LDAP_CONTROL_PROXY_AUTHZ,
208 (int)offsetof(struct slap_control_ids, sc_proxyAuthz),
209 SLAP_CTRL_GLOBAL|SLAP_CTRL_ACCESS,
210 proxy_authz_extops, NULL,
211 parseProxyAuthz, LDAP_SLIST_ENTRY_INITIALIZER(next) },
212 #ifdef SLAP_CONTROL_X_SESSION_TRACKING
213 { LDAP_CONTROL_X_SESSION_TRACKING,
214 (int)offsetof(struct slap_control_ids, sc_sessionTracking),
215 SLAP_CTRL_GLOBAL|SLAP_CTRL_ACCESS|SLAP_CTRL_BIND|SLAP_CTRL_HIDE,
216 session_tracking_extops, NULL,
217 parseSessionTracking, LDAP_SLIST_ENTRY_INITIALIZER(next) },
219 { NULL, 0, 0, NULL, 0, NULL, LDAP_SLIST_ENTRY_INITIALIZER(next) }
222 static struct slap_control *
223 find_ctrl( const char *oid );
226 * Register a supported control.
228 * This can be called by an OpenLDAP plugin or, indirectly, by a
229 * SLAPI plugin calling slapi_register_supported_control().
231 * NOTE: if flags == 1 the control is replaced if already registered;
232 * otherwise registering an already registered control is not allowed.
235 register_supported_control2(const char *controloid,
236 slap_mask_t controlmask,
238 SLAP_CTRL_PARSE_FN *controlparsefn,
242 struct slap_control *sc = NULL;
244 BerVarray extendedopsbv = NULL;
246 if ( num_known_controls >= SLAP_MAX_CIDS ) {
247 Debug( LDAP_DEBUG_ANY, "Too many controls registered."
248 " Recompile slapd with SLAP_MAX_CIDS defined > %d\n",
249 SLAP_MAX_CIDS, 0, 0 );
253 if ( controloid == NULL ) {
254 return LDAP_PARAM_ERROR;
257 /* check if already registered */
258 for ( i = 0; slap_known_controls[ i ]; i++ ) {
259 if ( strcmp( controloid, slap_known_controls[ i ] ) == 0 ) {
261 Debug( LDAP_DEBUG_TRACE,
262 "Control %s already registered; replacing.\n",
264 /* (find and) replace existing handler */
265 sc = find_ctrl( controloid );
266 assert( sc != NULL );
270 Debug( LDAP_DEBUG_ANY,
271 "Control %s already registered.\n",
273 return LDAP_PARAM_ERROR;
277 /* turn compatible extended operations into bervals */
278 if ( controlexops != NULL ) {
281 for ( i = 0; controlexops[ i ]; i++ );
283 extendedopsbv = ber_memcalloc( i + 1, sizeof( struct berval ) );
284 if ( extendedopsbv == NULL ) {
285 return LDAP_NO_MEMORY;
288 for ( i = 0; controlexops[ i ]; i++ ) {
289 ber_str2bv( controlexops[ i ], 0, 1, &extendedopsbv[ i ] );
294 sc = (struct slap_control *)SLAP_MALLOC( sizeof( *sc ) );
296 return LDAP_NO_MEMORY;
299 sc->sc_oid = ch_strdup( controloid );
300 sc->sc_cid = num_known_controls;
302 /* Update slap_known_controls, too. */
303 slap_known_controls[num_known_controls - 1] = sc->sc_oid;
304 slap_known_controls[num_known_controls++] = NULL;
306 LDAP_SLIST_NEXT( sc, sc_next ) = NULL;
307 LDAP_SLIST_INSERT_HEAD( &controls_list, sc, sc_next );
310 if ( sc->sc_extendedopsbv ) {
311 /* FIXME: in principle, we should rather merge
312 * existing extops with those supported by the
313 * new control handling implementation.
314 * In fact, whether a control is compatible with
315 * an extop should not be a matter of implementation.
316 * We likely also need a means for a newly
317 * registered extop to declare that it is
318 * comptible with an already registered control.
320 ber_bvarray_free( sc->sc_extendedopsbv );
321 sc->sc_extendedopsbv = NULL;
322 sc->sc_extendedops = NULL;
326 sc->sc_extendedopsbv = extendedopsbv;
327 sc->sc_mask = controlmask;
328 sc->sc_parse = controlparsefn;
330 *controlcid = sc->sc_cid;
337 * One-time initialization of internal controls.
340 slap_controls_init( void )
346 for ( i = 0; control_defs[i].sc_oid != NULL; i++ ) {
347 int *cid = (int *)(((char *)&slap_cids) + control_defs[i].sc_cid );
348 rc = register_supported_control( control_defs[i].sc_oid,
349 control_defs[i].sc_mask, control_defs[i].sc_extendedops,
350 control_defs[i].sc_parse, cid );
351 if ( rc != LDAP_SUCCESS ) break;
358 * Free memory associated with list of supported controls.
361 controls_destroy( void )
363 struct slap_control *sc;
365 while ( !LDAP_SLIST_EMPTY(&controls_list) ) {
366 sc = LDAP_SLIST_FIRST(&controls_list);
367 LDAP_SLIST_REMOVE_HEAD(&controls_list, sc_next);
369 ch_free( sc->sc_oid );
370 if ( sc->sc_extendedopsbv != NULL ) {
371 ber_bvarray_free( sc->sc_extendedopsbv );
378 * Format the supportedControl attribute of the root DSE,
379 * detailing which controls are supported by the directory
383 controls_root_dse_info( Entry *e )
385 AttributeDescription *ad_supportedControl
386 = slap_schema.si_ad_supportedControl;
387 struct berval vals[2];
388 struct slap_control *sc;
390 vals[1].bv_val = NULL;
393 LDAP_SLIST_FOREACH( sc, &controls_list, sc_next ) {
394 if( sc->sc_mask & SLAP_CTRL_HIDE ) continue;
396 vals[0].bv_val = sc->sc_oid;
397 vals[0].bv_len = strlen( sc->sc_oid );
399 if ( attr_merge( e, ad_supportedControl, vals, NULL ) ) {
408 * Return a list of OIDs and operation masks for supported
409 * controls. Used by SLAPI.
412 get_supported_controls(char ***ctrloidsp,
413 slap_mask_t **ctrlmasks)
418 struct slap_control *sc;
422 LDAP_SLIST_FOREACH( sc, &controls_list, sc_next ) {
432 oids = (char **)SLAP_MALLOC( (n + 1) * sizeof(char *) );
433 if ( oids == NULL ) {
434 return LDAP_NO_MEMORY;
436 masks = (slap_mask_t *)SLAP_MALLOC( (n + 1) * sizeof(slap_mask_t) );
437 if ( masks == NULL ) {
439 return LDAP_NO_MEMORY;
444 LDAP_SLIST_FOREACH( sc, &controls_list, sc_next ) {
445 oids[n] = ch_strdup( sc->sc_oid );
446 masks[n] = sc->sc_mask;
459 * Find a control given its OID.
461 static struct slap_control *
462 find_ctrl( const char *oid )
464 struct slap_control *sc;
466 LDAP_SLIST_FOREACH( sc, &controls_list, sc_next ) {
467 if ( strcmp( oid, sc->sc_oid ) == 0 ) {
476 slap_find_control_id(
480 struct slap_control *ctrl = find_ctrl( oid );
482 if ( cid ) *cid = ctrl->sc_cid;
485 return LDAP_CONTROL_NOT_FOUND;
489 slap_global_control( Operation *op, const char *oid, int *cid )
491 struct slap_control *ctrl = find_ctrl( oid );
493 if ( ctrl == NULL ) {
494 /* should not be reachable */
495 Debug( LDAP_DEBUG_ANY,
496 "slap_global_control: unrecognized control: %s\n",
498 return LDAP_CONTROL_NOT_FOUND;
501 if ( cid ) *cid = ctrl->sc_cid;
503 if ( ( ctrl->sc_mask & SLAP_CTRL_GLOBAL ) ||
504 ( ( op->o_tag & LDAP_REQ_SEARCH ) &&
505 ( ctrl->sc_mask & SLAP_CTRL_GLOBAL_SEARCH ) ) )
507 return LDAP_COMPARE_TRUE;
511 Debug( LDAP_DEBUG_TRACE,
512 "slap_global_control: unavailable control: %s\n",
516 return LDAP_COMPARE_FALSE;
519 void slap_free_ctrls(
521 LDAPControl **ctrls )
525 for (i=0; ctrls[i]; i++) {
526 op->o_tmpfree(ctrls[i], op->o_tmpmemctx );
528 op->o_tmpfree( ctrls, op->o_tmpmemctx );
534 LDAPControl *control,
537 struct slap_control *sc;
539 sc = find_ctrl( control->ldctl_oid );
541 /* recognized control */
543 switch( op->o_tag ) {
545 tagmask = SLAP_CTRL_ADD;
548 tagmask = SLAP_CTRL_BIND;
550 case LDAP_REQ_COMPARE:
551 tagmask = SLAP_CTRL_COMPARE;
553 case LDAP_REQ_DELETE:
554 tagmask = SLAP_CTRL_DELETE;
556 case LDAP_REQ_MODIFY:
557 tagmask = SLAP_CTRL_MODIFY;
559 case LDAP_REQ_RENAME:
560 tagmask = SLAP_CTRL_RENAME;
562 case LDAP_REQ_SEARCH:
563 tagmask = SLAP_CTRL_SEARCH;
565 case LDAP_REQ_UNBIND:
566 tagmask = SLAP_CTRL_UNBIND;
568 case LDAP_REQ_ABANDON:
569 tagmask = SLAP_CTRL_ABANDON;
571 case LDAP_REQ_EXTENDED:
573 assert( op->ore_reqoid.bv_val != NULL );
574 if( sc->sc_extendedopsbv != NULL ) {
576 for( i=0; !BER_BVISNULL( &sc->sc_extendedopsbv[i] ); i++ ) {
577 if( bvmatch( &op->ore_reqoid,
578 &sc->sc_extendedopsbv[i] ) )
587 *text = "controls internal error";
591 if (( sc->sc_mask & tagmask ) == tagmask ) {
592 /* available extension */
595 if( !sc->sc_parse ) {
596 *text = "not yet implemented";
600 rc = sc->sc_parse( op, rs, control );
602 assert( rc != LDAP_UNAVAILABLE_CRITICAL_EXTENSION );
606 } else if( control->ldctl_iscritical ) {
607 /* unavailable CRITICAL control */
608 *text = "critical extension is unavailable";
609 return LDAP_UNAVAILABLE_CRITICAL_EXTENSION;
611 } else if( control->ldctl_iscritical ) {
612 /* unrecognized CRITICAL control */
613 *text = "critical extension is not recognized";
614 return LDAP_UNAVAILABLE_CRITICAL_EXTENSION;
629 BerElement *ber = op->o_ber;
632 len = ber_pvt_ber_remaining(ber);
636 rs->sr_err = LDAP_SUCCESS;
640 if(( tag = ber_peek_tag( ber, &len )) != LDAP_TAG_CONTROLS ) {
641 if( tag == LBER_ERROR ) {
642 rs->sr_err = SLAPD_DISCONNECT;
643 rs->sr_text = "unexpected data in PDU";
649 Debug( LDAP_DEBUG_TRACE,
650 "=> get_ctrls\n", 0, 0, 0 );
652 if( op->o_protocol < LDAP_VERSION3 ) {
653 rs->sr_err = SLAPD_DISCONNECT;
654 rs->sr_text = "controls require LDAPv3";
658 /* one for first control, one for termination */
659 op->o_ctrls = op->o_tmpalloc( 2 * sizeof(LDAPControl *), op->o_tmpmemctx );
662 if( op->ctrls == NULL ) {
663 rs->sr_err = LDAP_NO_MEMORY;
664 rs->sr_text = "no memory";
669 op->o_ctrls[nctrls] = NULL;
671 /* step through each element */
672 for( tag = ber_first_element( ber, &len, &opaque );
674 tag = ber_next_element( ber, &len, opaque ) )
677 LDAPControl **tctrls;
679 c = op->o_tmpalloc( sizeof(LDAPControl), op->o_tmpmemctx );
680 memset(c, 0, sizeof(LDAPControl));
682 /* allocate pointer space for current controls (nctrls)
683 * + this control + extra NULL
685 tctrls = op->o_tmprealloc( op->o_ctrls,
686 (nctrls+2) * sizeof(LDAPControl *), op->o_tmpmemctx );
689 if( tctrls == NULL ) {
691 ldap_controls_free(op->o_ctrls);
694 rs->sr_err = LDAP_NO_MEMORY;
695 rs->sr_text = "no memory";
699 op->o_ctrls = tctrls;
701 op->o_ctrls[nctrls++] = c;
702 op->o_ctrls[nctrls] = NULL;
704 tag = ber_scanf( ber, "{m" /*}*/, &bv );
705 c->ldctl_oid = bv.bv_val;
707 if( tag == LBER_ERROR ) {
708 Debug( LDAP_DEBUG_TRACE, "=> get_ctrls: get oid failed.\n",
711 slap_free_ctrls( op, op->o_ctrls );
713 rs->sr_err = SLAPD_DISCONNECT;
714 rs->sr_text = "decoding controls error";
717 } else if( c->ldctl_oid == NULL ) {
718 Debug( LDAP_DEBUG_TRACE,
719 "get_ctrls: conn %lu got emtpy OID.\n",
720 op->o_connid, 0, 0 );
722 slap_free_ctrls( op, op->o_ctrls );
724 rs->sr_err = LDAP_PROTOCOL_ERROR;
725 rs->sr_text = "OID field is empty";
729 tag = ber_peek_tag( ber, &len );
731 if( tag == LBER_BOOLEAN ) {
733 tag = ber_scanf( ber, "b", &crit );
735 if( tag == LBER_ERROR ) {
736 Debug( LDAP_DEBUG_TRACE, "=> get_ctrls: get crit failed.\n",
738 slap_free_ctrls( op, op->o_ctrls );
740 rs->sr_err = SLAPD_DISCONNECT;
741 rs->sr_text = "decoding controls error";
745 c->ldctl_iscritical = (crit != 0);
746 tag = ber_peek_tag( ber, &len );
749 if( tag == LBER_OCTETSTRING ) {
750 tag = ber_scanf( ber, "m", &c->ldctl_value );
752 if( tag == LBER_ERROR ) {
753 Debug( LDAP_DEBUG_TRACE, "=> get_ctrls: conn %lu: "
754 "%s (%scritical): get value failed.\n",
755 op->o_connid, c->ldctl_oid,
756 c->ldctl_iscritical ? "" : "non" );
757 slap_free_ctrls( op, op->o_ctrls );
759 rs->sr_err = SLAPD_DISCONNECT;
760 rs->sr_text = "decoding controls error";
765 Debug( LDAP_DEBUG_TRACE,
766 "=> get_ctrls: oid=\"%s\" (%scritical)\n",
767 c->ldctl_oid, c->ldctl_iscritical ? "" : "non", 0 );
769 rs->sr_err = slap_parse_ctrl( op, rs, c, &rs->sr_text );
770 if ( rs->sr_err != LDAP_SUCCESS ) {
776 Debug( LDAP_DEBUG_TRACE,
777 "<= get_ctrls: n=%d rc=%d err=\"%s\"\n",
778 nctrls, rs->sr_err, rs->sr_text ? rs->sr_text : "");
780 if( sendres && rs->sr_err != LDAP_SUCCESS ) {
781 if( rs->sr_err == SLAPD_DISCONNECT ) {
782 rs->sr_err = LDAP_PROTOCOL_ERROR;
783 send_ldap_disconnect( op, rs );
784 rs->sr_err = SLAPD_DISCONNECT;
786 send_ldap_result( op, rs );
798 BI_chk_controls fnc )
802 switch ( op->o_ctrlflag[ ctrl ] ) {
803 case SLAP_CONTROL_NONCRITICAL:
804 for ( i = 0, j = -1; op->o_ctrls[ i ] != NULL; i++ ) {
805 if ( strcmp( op->o_ctrls[ i ]->ldctl_oid,
806 slap_known_controls[ ctrl - 1 ] ) == 0 )
813 rs->sr_err = LDAP_OTHER;
821 op->o_tmpfree( op->o_ctrls[ j ], op->o_tmpmemctx );
824 AC_MEMCPY( &op->o_ctrls[ j ], &op->o_ctrls[ j + 1 ],
825 ( i - j ) * sizeof( LDAPControl * ) );
828 op->o_tmpfree( op->o_ctrls, op->o_tmpmemctx );
832 op->o_ctrlflag[ ctrl ] = SLAP_CONTROL_IGNORED;
834 Debug( LDAP_DEBUG_ANY, "%s: "
835 "non-critical control \"%s\" not supported; stripped.\n",
836 op->o_log_prefix, slap_known_controls[ ctrl ], 0 );
839 case SLAP_CONTROL_IGNORED:
840 case SLAP_CONTROL_NONE:
841 rs->sr_err = SLAP_CB_CONTINUE;
844 case SLAP_CONTROL_CRITICAL:
845 rs->sr_err = LDAP_UNAVAILABLE_CRITICAL_EXTENSION;
849 Debug( LDAP_DEBUG_ANY, "%s: "
850 "critical control \"%s\" not supported.\n",
851 op->o_log_prefix, slap_known_controls[ ctrl ], 0 );
855 /* handle all cases! */
862 static int parseDontUseCopy (
867 if ( op->o_dontUseCopy != SLAP_CONTROL_NONE ) {
868 rs->sr_text = "dontUseCopy control specified multiple times";
869 return LDAP_PROTOCOL_ERROR;
872 if ( !BER_BVISNULL( &ctrl->ldctl_value )) {
873 rs->sr_text = "dontUseCopy control value not absent";
874 return LDAP_PROTOCOL_ERROR;
877 if ( !ctrl->ldctl_iscritical ) {
878 rs->sr_text = "dontUseCopy criticality of FALSE not allowed";
879 return LDAP_PROTOCOL_ERROR;
882 op->o_dontUseCopy = SLAP_CONTROL_CRITICAL;
886 static int parseRelax (
891 if ( op->o_relax != SLAP_CONTROL_NONE ) {
892 rs->sr_text = "relax control specified multiple times";
893 return LDAP_PROTOCOL_ERROR;
896 if ( !BER_BVISNULL( &ctrl->ldctl_value )) {
897 rs->sr_text = "relax control value not absent";
898 return LDAP_PROTOCOL_ERROR;
901 op->o_relax = ctrl->ldctl_iscritical
902 ? SLAP_CONTROL_CRITICAL
903 : SLAP_CONTROL_NONCRITICAL;
908 static int parseManageDSAit (
913 if ( op->o_managedsait != SLAP_CONTROL_NONE ) {
914 rs->sr_text = "manageDSAit control specified multiple times";
915 return LDAP_PROTOCOL_ERROR;
918 if ( !BER_BVISNULL( &ctrl->ldctl_value )) {
919 rs->sr_text = "manageDSAit control value not absent";
920 return LDAP_PROTOCOL_ERROR;
923 op->o_managedsait = ctrl->ldctl_iscritical
924 ? SLAP_CONTROL_CRITICAL
925 : SLAP_CONTROL_NONCRITICAL;
930 static int parseProxyAuthz (
936 struct berval dn = BER_BVNULL;
938 if ( op->o_proxy_authz != SLAP_CONTROL_NONE ) {
939 rs->sr_text = "proxy authorization control specified multiple times";
940 return LDAP_PROTOCOL_ERROR;
943 if ( BER_BVISNULL( &ctrl->ldctl_value )) {
944 rs->sr_text = "proxy authorization control value absent";
945 return LDAP_PROTOCOL_ERROR;
948 if ( !( global_allows & SLAP_ALLOW_PROXY_AUTHZ_ANON )
949 && BER_BVISEMPTY( &op->o_ndn ) )
951 rs->sr_text = "anonymous proxied authorization not allowed";
952 return LDAP_PROXIED_AUTHORIZATION_DENIED;
955 op->o_proxy_authz = ctrl->ldctl_iscritical
956 ? SLAP_CONTROL_CRITICAL
957 : SLAP_CONTROL_NONCRITICAL;
959 Debug( LDAP_DEBUG_ARGS,
960 "parseProxyAuthz: conn %lu authzid=\"%s\"\n",
962 ctrl->ldctl_value.bv_len ? ctrl->ldctl_value.bv_val : "anonymous",
965 if ( BER_BVISEMPTY( &ctrl->ldctl_value )) {
966 Debug( LDAP_DEBUG_TRACE,
967 "parseProxyAuthz: conn=%lu anonymous\n",
968 op->o_connid, 0, 0 );
971 if ( !BER_BVISNULL( &op->o_ndn ) ) {
972 op->o_ndn.bv_val[ 0 ] = '\0';
974 op->o_ndn.bv_len = 0;
976 if ( !BER_BVISNULL( &op->o_dn ) ) {
977 op->o_dn.bv_val[ 0 ] = '\0';
984 rc = slap_sasl_getdn( op->o_conn, op, &ctrl->ldctl_value,
985 NULL, &dn, SLAP_GETDN_AUTHZID );
987 /* FIXME: empty DN in proxyAuthz control should be legal... */
988 if( rc != LDAP_SUCCESS /* || !dn.bv_len */ ) {
990 ch_free( dn.bv_val );
992 rs->sr_text = "authzId mapping failed";
993 return LDAP_PROXIED_AUTHORIZATION_DENIED;
996 Debug( LDAP_DEBUG_TRACE,
997 "parseProxyAuthz: conn=%lu \"%s\"\n",
999 dn.bv_len ? dn.bv_val : "(NULL)", 0 );
1001 rc = slap_sasl_authorized( op, &op->o_ndn, &dn );
1004 ch_free( dn.bv_val );
1005 rs->sr_text = "not authorized to assume identity";
1006 return LDAP_PROXIED_AUTHORIZATION_DENIED;
1009 ch_free( op->o_ndn.bv_val );
1010 ch_free( op->o_dn.bv_val );
1013 * NOTE: since slap_sasl_getdn() returns a normalized dn,
1014 * from now on op->o_dn is normalized
1017 ber_dupbv( &op->o_dn, &dn );
1019 Statslog( LDAP_DEBUG_STATS, "%s PROXYAUTHZ dn=\"%s\"\n",
1020 op->o_log_prefix, dn.bv_val, 0, 0, 0 );
1022 return LDAP_SUCCESS;
1025 static int parseNoOp (
1030 if ( op->o_noop != SLAP_CONTROL_NONE ) {
1031 rs->sr_text = "noop control specified multiple times";
1032 return LDAP_PROTOCOL_ERROR;
1035 if ( !BER_BVISNULL( &ctrl->ldctl_value ) ) {
1036 rs->sr_text = "noop control value not empty";
1037 return LDAP_PROTOCOL_ERROR;
1040 op->o_noop = ctrl->ldctl_iscritical
1041 ? SLAP_CONTROL_CRITICAL
1042 : SLAP_CONTROL_NONCRITICAL;
1044 return LDAP_SUCCESS;
1047 static int parsePagedResults (
1052 int rc = LDAP_SUCCESS;
1056 struct berval cookie = BER_BVNULL;
1057 PagedResultsState *ps;
1059 if ( op->o_pagedresults != SLAP_CONTROL_NONE ) {
1060 rs->sr_text = "paged results control specified multiple times";
1061 return LDAP_PROTOCOL_ERROR;
1064 if ( BER_BVISNULL( &ctrl->ldctl_value ) ) {
1065 rs->sr_text = "paged results control value is absent";
1066 return LDAP_PROTOCOL_ERROR;
1069 if ( BER_BVISEMPTY( &ctrl->ldctl_value ) ) {
1070 rs->sr_text = "paged results control value is empty";
1071 return LDAP_PROTOCOL_ERROR;
1074 /* Parse the control value
1075 * realSearchControlValue ::= SEQUENCE {
1076 * size INTEGER (0..maxInt),
1077 * -- requested page size from client
1078 * -- result set size estimate from server
1079 * cookie OCTET STRING
1082 ber = ber_init( &ctrl->ldctl_value );
1083 if ( ber == NULL ) {
1084 rs->sr_text = "internal error";
1088 tag = ber_scanf( ber, "{im}", &size, &cookie );
1090 if ( tag == LBER_ERROR ) {
1091 rs->sr_text = "paged results control could not be decoded";
1092 rc = LDAP_PROTOCOL_ERROR;
1097 rs->sr_text = "paged results control size invalid";
1098 rc = LDAP_PROTOCOL_ERROR;
1102 ps = op->o_tmpalloc( sizeof(PagedResultsState), op->o_tmpmemctx );
1103 *ps = op->o_conn->c_pagedresults_state;
1105 op->o_pagedresults_state = ps;
1107 /* NOTE: according to RFC 2696 3.:
1109 If the page size is greater than or equal to the sizeLimit value, the
1110 server should ignore the control as the request can be satisfied in a
1113 * NOTE: this assumes that the op->ors_slimit be set
1114 * before the controls are parsed.
1117 if ( op->ors_slimit > 0 && size >= op->ors_slimit ) {
1118 op->o_pagedresults = SLAP_CONTROL_IGNORED;
1120 } else if ( ctrl->ldctl_iscritical ) {
1121 op->o_pagedresults = SLAP_CONTROL_CRITICAL;
1124 op->o_pagedresults = SLAP_CONTROL_NONCRITICAL;
1128 (void)ber_free( ber, 1 );
1132 #ifdef SLAP_CONTROL_X_SORTEDRESULTS
1133 static int parseSortedResults (
1138 int rc = LDAP_SUCCESS;
1140 if ( op->o_sortedresults != SLAP_CONTROL_NONE ) {
1141 rs->sr_text = "sorted results control specified multiple times";
1142 return LDAP_PROTOCOL_ERROR;
1145 if ( BER_BVISNULL( &ctrl->ldctl_value ) ) {
1146 rs->sr_text = "sorted results control value is absent";
1147 return LDAP_PROTOCOL_ERROR;
1150 if ( BER_BVISEMPTY( &ctrl->ldctl_value ) ) {
1151 rs->sr_text = "sorted results control value is empty";
1152 return LDAP_PROTOCOL_ERROR;
1155 /* blow off parsing the value */
1157 op->o_sortedresults = ctrl->ldctl_iscritical
1158 ? SLAP_CONTROL_CRITICAL
1159 : SLAP_CONTROL_NONCRITICAL;
1165 static int parseAssert (
1171 struct berval fstr = BER_BVNULL;
1173 if ( op->o_assert != SLAP_CONTROL_NONE ) {
1174 rs->sr_text = "assert control specified multiple times";
1175 return LDAP_PROTOCOL_ERROR;
1178 if ( BER_BVISNULL( &ctrl->ldctl_value )) {
1179 rs->sr_text = "assert control value is absent";
1180 return LDAP_PROTOCOL_ERROR;
1183 if ( BER_BVISEMPTY( &ctrl->ldctl_value )) {
1184 rs->sr_text = "assert control value is empty";
1185 return LDAP_PROTOCOL_ERROR;
1188 ber = ber_init( &(ctrl->ldctl_value) );
1190 rs->sr_text = "assert control: internal error";
1194 rs->sr_err = get_filter( op, ber, (Filter **)&(op->o_assertion),
1196 (void) ber_free( ber, 1 );
1197 if( rs->sr_err != LDAP_SUCCESS ) {
1198 if( rs->sr_err == SLAPD_DISCONNECT ) {
1199 rs->sr_err = LDAP_PROTOCOL_ERROR;
1200 send_ldap_disconnect( op, rs );
1201 rs->sr_err = SLAPD_DISCONNECT;
1203 send_ldap_result( op, rs );
1205 if( op->o_assertion != NULL ) {
1206 filter_free_x( op, op->o_assertion );
1212 filter2bv_x( op, op->o_assertion, &fstr );
1214 Debug( LDAP_DEBUG_ARGS, "parseAssert: conn %ld assert: %s\n",
1215 op->o_connid, fstr.bv_len ? fstr.bv_val : "empty" , 0 );
1216 op->o_tmpfree( fstr.bv_val, op->o_tmpmemctx );
1219 op->o_assert = ctrl->ldctl_iscritical
1220 ? SLAP_CONTROL_CRITICAL
1221 : SLAP_CONTROL_NONCRITICAL;
1223 rs->sr_err = LDAP_SUCCESS;
1224 return LDAP_SUCCESS;
1227 static int parsePreRead (
1232 ber_len_t siz, off, i;
1233 AttributeName *an = NULL;
1236 if ( op->o_preread != SLAP_CONTROL_NONE ) {
1237 rs->sr_text = "preread control specified multiple times";
1238 return LDAP_PROTOCOL_ERROR;
1241 if ( BER_BVISNULL( &ctrl->ldctl_value )) {
1242 rs->sr_text = "preread control value is absent";
1243 return LDAP_PROTOCOL_ERROR;
1246 if ( BER_BVISEMPTY( &ctrl->ldctl_value )) {
1247 rs->sr_text = "preread control value is empty";
1248 return LDAP_PROTOCOL_ERROR;
1252 if ( op->o_txnSpec ) { /* temporary limitation */
1253 rs->sr_text = "cannot perform pre-read in transaction";
1254 return LDAP_UNWILLING_TO_PERFORM;
1258 ber = ber_init( &(ctrl->ldctl_value) );
1260 rs->sr_text = "preread control: internal error";
1264 rs->sr_err = LDAP_SUCCESS;
1266 siz = sizeof( AttributeName );
1267 off = offsetof( AttributeName, an_name );
1268 if ( ber_scanf( ber, "{M}", &an, &siz, off ) == LBER_ERROR ) {
1269 rs->sr_text = "preread control: decoding error";
1270 rs->sr_err = LDAP_PROTOCOL_ERROR;
1274 for( i=0; i<siz; i++ ) {
1275 const char *dummy = NULL;
1277 an[i].an_desc = NULL;
1279 an[i].an_oc_exclude = 0;
1280 rs->sr_err = slap_bv2ad( &an[i].an_name, &an[i].an_desc, &dummy );
1281 if ( rs->sr_err != LDAP_SUCCESS && ctrl->ldctl_iscritical ) {
1284 : "postread control: unknown attributeType";
1289 op->o_preread = ctrl->ldctl_iscritical
1290 ? SLAP_CONTROL_CRITICAL
1291 : SLAP_CONTROL_NONCRITICAL;
1293 op->o_preread_attrs = an;
1296 (void) ber_free( ber, 1 );
1300 static int parsePostRead (
1305 ber_len_t siz, off, i;
1306 AttributeName *an = NULL;
1309 if ( op->o_postread != SLAP_CONTROL_NONE ) {
1310 rs->sr_text = "postread control specified multiple times";
1311 return LDAP_PROTOCOL_ERROR;
1314 if ( BER_BVISNULL( &ctrl->ldctl_value )) {
1315 rs->sr_text = "postread control value is absent";
1316 return LDAP_PROTOCOL_ERROR;
1319 if ( BER_BVISEMPTY( &ctrl->ldctl_value )) {
1320 rs->sr_text = "postread control value is empty";
1321 return LDAP_PROTOCOL_ERROR;
1325 if ( op->o_txnSpec ) { /* temporary limitation */
1326 rs->sr_text = "cannot perform post-read in transaction";
1327 return LDAP_UNWILLING_TO_PERFORM;
1331 ber = ber_init( &(ctrl->ldctl_value) );
1333 rs->sr_text = "postread control: internal error";
1337 rs->sr_err = LDAP_SUCCESS;
1338 siz = sizeof( AttributeName );
1339 off = offsetof( AttributeName, an_name );
1340 if ( ber_scanf( ber, "{M}", &an, &siz, off ) == LBER_ERROR ) {
1341 rs->sr_text = "postread control: decoding error";
1342 rs->sr_err = LDAP_PROTOCOL_ERROR;
1346 for ( i = 0; i < siz; i++ ) {
1347 const char *dummy = NULL;
1350 an[i].an_desc = NULL;
1352 an[i].an_oc_exclude = 0;
1353 rc = slap_bv2ad( &an[i].an_name, &an[i].an_desc, &dummy );
1354 if ( rc != LDAP_SUCCESS ) {
1356 static struct berval special_attrs[] = {
1357 BER_BVC( LDAP_NO_ATTRS ),
1358 BER_BVC( LDAP_ALL_USER_ATTRIBUTES ),
1359 BER_BVC( LDAP_ALL_OPERATIONAL_ATTRIBUTES ),
1363 /* deal with special attribute types */
1364 for ( i = 0; !BER_BVISNULL( &special_attrs[ i ] ); i++ ) {
1365 if ( bvmatch( &an[i].an_name, &special_attrs[ i ] ) ) {
1370 if ( BER_BVISNULL( &special_attrs[ i ] ) && ctrl->ldctl_iscritical ) {
1374 : "postread control: unknown attributeType";
1380 op->o_postread = ctrl->ldctl_iscritical
1381 ? SLAP_CONTROL_CRITICAL
1382 : SLAP_CONTROL_NONCRITICAL;
1384 op->o_postread_attrs = an;
1387 (void) ber_free( ber, 1 );
1391 static int parseValuesReturnFilter (
1397 struct berval fstr = BER_BVNULL;
1399 if ( op->o_valuesreturnfilter != SLAP_CONTROL_NONE ) {
1400 rs->sr_text = "valuesReturnFilter control specified multiple times";
1401 return LDAP_PROTOCOL_ERROR;
1404 if ( BER_BVISNULL( &ctrl->ldctl_value )) {
1405 rs->sr_text = "valuesReturnFilter control value is absent";
1406 return LDAP_PROTOCOL_ERROR;
1409 if ( BER_BVISEMPTY( &ctrl->ldctl_value )) {
1410 rs->sr_text = "valuesReturnFilter control value is empty";
1411 return LDAP_PROTOCOL_ERROR;
1414 ber = ber_init( &(ctrl->ldctl_value) );
1416 rs->sr_text = "internal error";
1420 rs->sr_err = get_vrFilter( op, ber,
1421 (ValuesReturnFilter **)&(op->o_vrFilter), &rs->sr_text);
1423 (void) ber_free( ber, 1 );
1425 if( rs->sr_err != LDAP_SUCCESS ) {
1426 if( rs->sr_err == SLAPD_DISCONNECT ) {
1427 rs->sr_err = LDAP_PROTOCOL_ERROR;
1428 send_ldap_disconnect( op, rs );
1429 rs->sr_err = SLAPD_DISCONNECT;
1431 send_ldap_result( op, rs );
1433 if( op->o_vrFilter != NULL) vrFilter_free( op, op->o_vrFilter );
1437 vrFilter2bv( op, op->o_vrFilter, &fstr );
1440 Debug( LDAP_DEBUG_ARGS, " vrFilter: %s\n",
1441 fstr.bv_len ? fstr.bv_val : "empty", 0, 0 );
1442 op->o_tmpfree( fstr.bv_val, op->o_tmpmemctx );
1445 op->o_valuesreturnfilter = ctrl->ldctl_iscritical
1446 ? SLAP_CONTROL_CRITICAL
1447 : SLAP_CONTROL_NONCRITICAL;
1449 rs->sr_err = LDAP_SUCCESS;
1450 return LDAP_SUCCESS;
1453 static int parseSubentries (
1458 if ( op->o_subentries != SLAP_CONTROL_NONE ) {
1459 rs->sr_text = "subentries control specified multiple times";
1460 return LDAP_PROTOCOL_ERROR;
1463 /* FIXME: should use BER library */
1464 if( ( ctrl->ldctl_value.bv_len != 3 )
1465 || ( ctrl->ldctl_value.bv_val[0] != 0x01 )
1466 || ( ctrl->ldctl_value.bv_val[1] != 0x01 ))
1468 rs->sr_text = "subentries control value encoding is bogus";
1469 return LDAP_PROTOCOL_ERROR;
1472 op->o_subentries = ctrl->ldctl_iscritical
1473 ? SLAP_CONTROL_CRITICAL
1474 : SLAP_CONTROL_NONCRITICAL;
1476 if (ctrl->ldctl_value.bv_val[2]) {
1477 set_subentries_visibility( op );
1480 return LDAP_SUCCESS;
1483 static int parsePermissiveModify (
1488 if ( op->o_permissive_modify != SLAP_CONTROL_NONE ) {
1489 rs->sr_text = "permissiveModify control specified multiple times";
1490 return LDAP_PROTOCOL_ERROR;
1493 if ( BER_BVISNULL( &ctrl->ldctl_value )) {
1494 rs->sr_text = "permissiveModify control value not absent";
1495 return LDAP_PROTOCOL_ERROR;
1498 op->o_permissive_modify = ctrl->ldctl_iscritical
1499 ? SLAP_CONTROL_CRITICAL
1500 : SLAP_CONTROL_NONCRITICAL;
1502 return LDAP_SUCCESS;
1505 static int parseDomainScope (
1510 if ( op->o_domain_scope != SLAP_CONTROL_NONE ) {
1511 rs->sr_text = "domainScope control specified multiple times";
1512 return LDAP_PROTOCOL_ERROR;
1515 if ( BER_BVISNULL( &ctrl->ldctl_value )) {
1516 rs->sr_text = "domainScope control value not empty";
1517 return LDAP_PROTOCOL_ERROR;
1520 op->o_domain_scope = ctrl->ldctl_iscritical
1521 ? SLAP_CONTROL_CRITICAL
1522 : SLAP_CONTROL_NONCRITICAL;
1524 return LDAP_SUCCESS;
1527 #ifdef SLAP_CONTROL_X_TREE_DELETE
1528 static int parseTreeDelete (
1533 if ( op->o_tree_delete != SLAP_CONTROL_NONE ) {
1534 rs->sr_text = "treeDelete control specified multiple times";
1535 return LDAP_PROTOCOL_ERROR;
1538 if ( !BER_BVISNULL( &ctrl->ldctl_value )) {
1539 rs->sr_text = "treeDelete control value not absent";
1540 return LDAP_PROTOCOL_ERROR;
1543 op->o_tree_delete = ctrl->ldctl_iscritical
1544 ? SLAP_CONTROL_CRITICAL
1545 : SLAP_CONTROL_NONCRITICAL;
1547 return LDAP_SUCCESS;
1551 static int parseSearchOptions (
1557 ber_int_t search_flags;
1560 if ( BER_BVISNULL( &ctrl->ldctl_value )) {
1561 rs->sr_text = "searchOptions control value is absent";
1562 return LDAP_PROTOCOL_ERROR;
1565 if ( BER_BVISEMPTY( &ctrl->ldctl_value )) {
1566 rs->sr_text = "searchOptions control value is empty";
1567 return LDAP_PROTOCOL_ERROR;
1570 ber = ber_init( &ctrl->ldctl_value );
1572 rs->sr_text = "internal error";
1576 tag = ber_scanf( ber, "{i}", &search_flags );
1577 (void) ber_free( ber, 1 );
1579 if ( tag == LBER_ERROR ) {
1580 rs->sr_text = "searchOptions control decoding error";
1581 return LDAP_PROTOCOL_ERROR;
1584 if ( search_flags & LDAP_SEARCH_FLAG_DOMAIN_SCOPE ) {
1585 if ( op->o_domain_scope != SLAP_CONTROL_NONE ) {
1586 rs->sr_text = "searchOptions control specified multiple times "
1587 "or with domainScope control";
1588 return LDAP_PROTOCOL_ERROR;
1591 op->o_domain_scope = ctrl->ldctl_iscritical
1592 ? SLAP_CONTROL_CRITICAL
1593 : SLAP_CONTROL_NONCRITICAL;
1596 if ( search_flags & ~(LDAP_SEARCH_FLAG_DOMAIN_SCOPE) ) {
1597 /* Other search flags not recognised so far,
1599 * LDAP_SEARCH_FLAG_PHANTOM_ROOM
1601 rs->sr_text = "searchOptions contained unrecognized flag";
1602 return LDAP_UNWILLING_TO_PERFORM;
1605 return LDAP_SUCCESS;
1608 #ifdef SLAP_CONTROL_X_SESSION_TRACKING
1609 static int parseSessionTracking(
1619 struct berval sessionSourceIp = BER_BVNULL,
1620 sessionSourceName = BER_BVNULL,
1621 formatOID = BER_BVNULL,
1622 sessionTrackingIdentifier = BER_BVNULL;
1624 size_t st_len, st_pos;
1626 if ( ctrl->ldctl_iscritical ) {
1627 rs->sr_text = "sessionTracking criticality is TRUE";
1628 return LDAP_PROTOCOL_ERROR;
1631 if ( BER_BVISNULL( &ctrl->ldctl_value ) ) {
1632 rs->sr_text = "sessionTracking control value is absent";
1633 return LDAP_PROTOCOL_ERROR;
1636 if ( BER_BVISEMPTY( &ctrl->ldctl_value ) ) {
1637 rs->sr_text = "sessionTracking control value is empty";
1638 return LDAP_PROTOCOL_ERROR;
1641 ber = ber_init( &ctrl->ldctl_value );
1642 if ( ber == NULL ) {
1643 rs->sr_text = "internal error";
1647 tag = ber_skip_tag( ber, &len );
1648 if ( tag != LBER_SEQUENCE ) {
1653 /* sessionSourceIp */
1654 tag = ber_peek_tag( ber, &len );
1655 if ( tag == LBER_DEFAULT ) {
1661 tag = ber_skip_tag( ber, &len );
1663 } else if ( len > 128 ) {
1664 rs->sr_text = "sessionTracking.sessionSourceIp too long";
1665 rs->sr_err = LDAP_PROTOCOL_ERROR;
1669 tag = ber_scanf( ber, "m", &sessionSourceIp );
1672 if ( ldif_is_not_printable( sessionSourceIp.bv_val, sessionSourceIp.bv_len ) ) {
1673 BER_BVZERO( &sessionSourceIp );
1676 /* sessionSourceName */
1677 tag = ber_peek_tag( ber, &len );
1678 if ( tag == LBER_DEFAULT ) {
1684 tag = ber_skip_tag( ber, &len );
1686 } else if ( len > 65536 ) {
1687 rs->sr_text = "sessionTracking.sessionSourceName too long";
1688 rs->sr_err = LDAP_PROTOCOL_ERROR;
1692 tag = ber_scanf( ber, "m", &sessionSourceName );
1695 if ( ldif_is_not_printable( sessionSourceName.bv_val, sessionSourceName.bv_len ) ) {
1696 BER_BVZERO( &sessionSourceName );
1700 tag = ber_peek_tag( ber, &len );
1701 if ( tag == LBER_DEFAULT ) {
1707 rs->sr_text = "sessionTracking.formatOID empty";
1708 rs->sr_err = LDAP_PROTOCOL_ERROR;
1711 } else if ( len > 1024 ) {
1712 rs->sr_text = "sessionTracking.formatOID too long";
1713 rs->sr_err = LDAP_PROTOCOL_ERROR;
1717 tag = ber_scanf( ber, "m", &formatOID );
1720 rc = numericoidValidate( NULL, &formatOID );
1721 if ( rc != LDAP_SUCCESS ) {
1722 rs->sr_text = "sessionTracking.formatOID invalid";
1726 /* sessionTrackingIdentifier */
1727 tag = ber_peek_tag( ber, &len );
1728 if ( tag == LBER_DEFAULT ) {
1734 tag = ber_skip_tag( ber, &len );
1737 /* note: should not be more than 65536... */
1738 tag = ber_scanf( ber, "m", &sessionTrackingIdentifier );
1741 if ( ldif_is_not_printable( sessionTrackingIdentifier.bv_val, sessionTrackingIdentifier.bv_len ) ) {
1742 BER_BVZERO( &sessionTrackingIdentifier );
1746 tag = ber_skip_tag( ber, &len );
1747 if ( tag == LBER_DEFAULT && len == 0 ) {
1752 if ( !BER_BVISNULL( &sessionSourceIp ) ) {
1753 st_len += STRLENOF( "IP=" ) + sessionSourceIp.bv_len;
1755 if ( !BER_BVISNULL( &sessionSourceName ) ) {
1756 if ( st_len ) st_len++;
1757 st_len += STRLENOF( "NAME=" ) + sessionSourceName.bv_len;
1759 if ( !BER_BVISNULL( &sessionTrackingIdentifier ) ) {
1760 if ( st_len ) st_len++;
1761 st_len += STRLENOF( "ID=" ) + sessionTrackingIdentifier.bv_len;
1764 if ( st_len == 0 ) {
1768 st_len += STRLENOF( " []" );
1769 st_pos = strlen( op->o_log_prefix );
1771 if ( sizeof( op->o_log_prefix ) - st_pos > st_len ) {
1772 char *ptr = &op->o_log_prefix[ st_pos ];
1774 ptr = lutil_strcopy( ptr, " [" /*]*/ );
1777 if ( !BER_BVISNULL( &sessionSourceIp ) ) {
1778 ptr = lutil_strcopy( ptr, "IP=" );
1779 ptr = lutil_strcopy( ptr, sessionSourceIp.bv_val );
1783 if ( !BER_BVISNULL( &sessionSourceName ) ) {
1784 if ( st_len ) *ptr++ = ' ';
1785 ptr = lutil_strcopy( ptr, "NAME=" );
1786 ptr = lutil_strcopy( ptr, sessionSourceName.bv_val );
1790 if ( !BER_BVISNULL( &sessionTrackingIdentifier ) ) {
1791 if ( st_len ) *ptr++ = ' ';
1792 ptr = lutil_strcopy( ptr, "ID=" );
1793 ptr = lutil_strcopy( ptr, sessionTrackingIdentifier.bv_val );
1801 (void)ber_free( ber, 1 );
1803 if ( tag == LBER_ERROR ) {
1804 rs->sr_text = "sessionTracking control decoding error";
1805 return LDAP_PROTOCOL_ERROR;