1 /* $OpenLDAP: pkg/ldap/servers/slapd/controls.c,v 1.174.2.10 2008/04/14 22:15:21 quanah Exp $ */
2 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
4 * Copyright 1998-2008 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
;
52 #undef sc_mask /* avoid conflict with Irix 6.5 <sys/signal.h> */
54 const struct berval slap_pre_read_bv
= BER_BVC(LDAP_CONTROL_PRE_READ
);
55 const struct berval slap_post_read_bv
= BER_BVC(LDAP_CONTROL_POST_READ
);
57 struct slap_control_ids slap_cids
;
63 /* The controlID for this control */
66 /* Operations supported by control */
69 /* Extended operations supported by control */
70 char **sc_extendedops
; /* input */
71 BerVarray sc_extendedopsbv
; /* run-time use */
73 /* Control parsing callback */
74 SLAP_CTRL_PARSE_FN
*sc_parse
;
76 LDAP_SLIST_ENTRY(slap_control
) sc_next
;
79 static LDAP_SLIST_HEAD(ControlsList
, slap_control
) controls_list
80 = LDAP_SLIST_HEAD_INITIALIZER(&controls_list
);
83 * all known request control OIDs should be added to this list
86 * NOTE: initialize num_known_controls to 1 so that cid = 0 always
87 * addresses an undefined control; this allows to safely test for
88 * well known controls even if they are not registered, e.g. if
89 * they get moved to modules. An example is sc_LDAPsync, which
90 * is implemented in the syncprov overlay and thus, if configured
91 * as dynamic module, may not be registered. One side effect is that
92 * slap_known_controls[0] == NULL, so it should always be used
94 * FIXME: should we define the "undefined control" oid?
96 char *slap_known_controls
[SLAP_MAX_CIDS
+1];
97 static int num_known_controls
= 1;
99 static char *proxy_authz_extops
[] = {
100 LDAP_EXOP_MODIFY_PASSWD
,
106 static char *manageDSAit_extops
[] = {
111 #ifdef SLAP_CONTROL_X_SESSION_TRACKING
112 static char *session_tracking_extops
[] = {
113 LDAP_EXOP_MODIFY_PASSWD
,
120 static struct slap_control control_defs
[] = {
121 { LDAP_CONTROL_ASSERT
,
122 (int)offsetof(struct slap_control_ids
, sc_assert
),
123 SLAP_CTRL_DELETE
|SLAP_CTRL_MODIFY
|SLAP_CTRL_RENAME
|
124 SLAP_CTRL_COMPARE
|SLAP_CTRL_SEARCH
,
126 parseAssert
, LDAP_SLIST_ENTRY_INITIALIZER(next
) },
127 { LDAP_CONTROL_PRE_READ
,
128 (int)offsetof(struct slap_control_ids
, sc_preRead
),
129 SLAP_CTRL_DELETE
|SLAP_CTRL_MODIFY
|SLAP_CTRL_RENAME
,
131 parsePreRead
, LDAP_SLIST_ENTRY_INITIALIZER(next
) },
132 { LDAP_CONTROL_POST_READ
,
133 (int)offsetof(struct slap_control_ids
, sc_postRead
),
134 SLAP_CTRL_ADD
|SLAP_CTRL_MODIFY
|SLAP_CTRL_RENAME
,
136 parsePostRead
, LDAP_SLIST_ENTRY_INITIALIZER(next
) },
137 { LDAP_CONTROL_VALUESRETURNFILTER
,
138 (int)offsetof(struct slap_control_ids
, sc_valuesReturnFilter
),
139 SLAP_CTRL_GLOBAL
|SLAP_CTRL_SEARCH
,
141 parseValuesReturnFilter
, LDAP_SLIST_ENTRY_INITIALIZER(next
) },
142 { LDAP_CONTROL_PAGEDRESULTS
,
143 (int)offsetof(struct slap_control_ids
, sc_pagedResults
),
146 parsePagedResults
, LDAP_SLIST_ENTRY_INITIALIZER(next
) },
147 #ifdef SLAP_CONTROL_X_SORTEDRESULTS
148 { LDAP_CONTROL_SORTREQUEST
,
149 (int)offsetof(struct slap_control_ids
, sc_sortedResults
),
150 SLAP_CTRL_GLOBAL
|SLAP_CTRL_SEARCH
|SLAP_CTRL_HIDE
,
152 parseSortedResults
, LDAP_SLIST_ENTRY_INITIALIZER(next
) },
154 { LDAP_CONTROL_X_DOMAIN_SCOPE
,
155 (int)offsetof(struct slap_control_ids
, sc_domainScope
),
156 SLAP_CTRL_GLOBAL
|SLAP_CTRL_SEARCH
|SLAP_CTRL_HIDE
,
158 parseDomainScope
, LDAP_SLIST_ENTRY_INITIALIZER(next
) },
159 { LDAP_CONTROL_DONTUSECOPY
,
160 (int)offsetof(struct slap_control_ids
, sc_dontUseCopy
),
161 SLAP_CTRL_GLOBAL
|SLAP_CTRL_INTROGATE
|SLAP_CTRL_HIDE
,
163 parseDontUseCopy
, LDAP_SLIST_ENTRY_INITIALIZER(next
) },
164 { LDAP_CONTROL_X_PERMISSIVE_MODIFY
,
165 (int)offsetof(struct slap_control_ids
, sc_permissiveModify
),
166 SLAP_CTRL_MODIFY
|SLAP_CTRL_HIDE
,
168 parsePermissiveModify
, LDAP_SLIST_ENTRY_INITIALIZER(next
) },
169 #ifdef SLAP_CONTROL_X_TREE_DELETE
170 { LDAP_CONTROL_X_TREE_DELETE
,
171 (int)offsetof(struct slap_control_ids
, sc_treeDelete
),
172 SLAP_CTRL_DELETE
|SLAP_CTRL_HIDE
,
174 parseTreeDelete
, LDAP_SLIST_ENTRY_INITIALIZER(next
) },
176 { LDAP_CONTROL_X_SEARCH_OPTIONS
,
177 (int)offsetof(struct slap_control_ids
, sc_searchOptions
),
178 SLAP_CTRL_GLOBAL
|SLAP_CTRL_SEARCH
|SLAP_CTRL_HIDE
,
180 parseSearchOptions
, LDAP_SLIST_ENTRY_INITIALIZER(next
) },
181 { LDAP_CONTROL_SUBENTRIES
,
182 (int)offsetof(struct slap_control_ids
, sc_subentries
),
185 parseSubentries
, LDAP_SLIST_ENTRY_INITIALIZER(next
) },
187 (int)offsetof(struct slap_control_ids
, sc_noOp
),
188 SLAP_CTRL_ACCESS
|SLAP_CTRL_HIDE
,
190 parseNoOp
, LDAP_SLIST_ENTRY_INITIALIZER(next
) },
191 { LDAP_CONTROL_RELAX
,
192 (int)offsetof(struct slap_control_ids
, sc_relax
),
193 SLAP_CTRL_GLOBAL
|SLAP_CTRL_UPDATE
|SLAP_CTRL_HIDE
,
195 parseRelax
, LDAP_SLIST_ENTRY_INITIALIZER(next
) },
197 { LDAP_CONTROL_X_TXN_SPEC
,
198 (int)offsetof(struct slap_control_ids
, sc_txnSpec
),
199 SLAP_CTRL_UPDATE
|SLAP_CTRL_HIDE
,
201 txn_spec_ctrl
, LDAP_SLIST_ENTRY_INITIALIZER(next
) },
203 { LDAP_CONTROL_MANAGEDSAIT
,
204 (int)offsetof(struct slap_control_ids
, sc_manageDSAit
),
206 manageDSAit_extops
, NULL
,
207 parseManageDSAit
, LDAP_SLIST_ENTRY_INITIALIZER(next
) },
208 { LDAP_CONTROL_PROXY_AUTHZ
,
209 (int)offsetof(struct slap_control_ids
, sc_proxyAuthz
),
210 SLAP_CTRL_GLOBAL
|SLAP_CTRL_ACCESS
,
211 proxy_authz_extops
, NULL
,
212 parseProxyAuthz
, LDAP_SLIST_ENTRY_INITIALIZER(next
) },
213 #ifdef SLAP_CONTROL_X_SESSION_TRACKING
214 { LDAP_CONTROL_X_SESSION_TRACKING
,
215 (int)offsetof(struct slap_control_ids
, sc_sessionTracking
),
216 SLAP_CTRL_GLOBAL
|SLAP_CTRL_ACCESS
|SLAP_CTRL_BIND
|SLAP_CTRL_HIDE
,
217 session_tracking_extops
, NULL
,
218 parseSessionTracking
, LDAP_SLIST_ENTRY_INITIALIZER(next
) },
220 { NULL
, 0, 0, NULL
, 0, NULL
, LDAP_SLIST_ENTRY_INITIALIZER(next
) }
223 static struct slap_control
*
224 find_ctrl( const char *oid
);
227 * Register a supported control.
229 * This can be called by an OpenLDAP plugin or, indirectly, by a
230 * SLAPI plugin calling slapi_register_supported_control().
232 * NOTE: if flags == 1 the control is replaced if already registered;
233 * otherwise registering an already registered control is not allowed.
236 register_supported_control2(const char *controloid
,
237 slap_mask_t controlmask
,
239 SLAP_CTRL_PARSE_FN
*controlparsefn
,
243 struct slap_control
*sc
= NULL
;
245 BerVarray extendedopsbv
= NULL
;
247 if ( num_known_controls
>= SLAP_MAX_CIDS
) {
248 Debug( LDAP_DEBUG_ANY
, "Too many controls registered."
249 " Recompile slapd with SLAP_MAX_CIDS defined > %d\n",
250 SLAP_MAX_CIDS
, 0, 0 );
254 if ( controloid
== NULL
) {
255 return LDAP_PARAM_ERROR
;
258 /* check if already registered */
259 for ( i
= 0; slap_known_controls
[ i
]; i
++ ) {
260 if ( strcmp( controloid
, slap_known_controls
[ i
] ) == 0 ) {
262 Debug( LDAP_DEBUG_TRACE
,
263 "Control %s already registered; replacing.\n",
265 /* (find and) replace existing handler */
266 sc
= find_ctrl( controloid
);
267 assert( sc
!= NULL
);
271 Debug( LDAP_DEBUG_ANY
,
272 "Control %s already registered.\n",
274 return LDAP_PARAM_ERROR
;
278 /* turn compatible extended operations into bervals */
279 if ( controlexops
!= NULL
) {
282 for ( i
= 0; controlexops
[ i
]; i
++ );
284 extendedopsbv
= ber_memcalloc( i
+ 1, sizeof( struct berval
) );
285 if ( extendedopsbv
== NULL
) {
286 return LDAP_NO_MEMORY
;
289 for ( i
= 0; controlexops
[ i
]; i
++ ) {
290 ber_str2bv( controlexops
[ i
], 0, 1, &extendedopsbv
[ i
] );
295 sc
= (struct slap_control
*)SLAP_MALLOC( sizeof( *sc
) );
297 return LDAP_NO_MEMORY
;
300 sc
->sc_oid
= ch_strdup( controloid
);
301 sc
->sc_cid
= num_known_controls
;
303 /* Update slap_known_controls, too. */
304 slap_known_controls
[num_known_controls
- 1] = sc
->sc_oid
;
305 slap_known_controls
[num_known_controls
++] = NULL
;
307 LDAP_SLIST_NEXT( sc
, sc_next
) = NULL
;
308 LDAP_SLIST_INSERT_HEAD( &controls_list
, sc
, sc_next
);
311 if ( sc
->sc_extendedopsbv
) {
312 /* FIXME: in principle, we should rather merge
313 * existing extops with those supported by the
314 * new control handling implementation.
315 * In fact, whether a control is compatible with
316 * an extop should not be a matter of implementation.
317 * We likely also need a means for a newly
318 * registered extop to declare that it is
319 * comptible with an already registered control.
321 ber_bvarray_free( sc
->sc_extendedopsbv
);
322 sc
->sc_extendedopsbv
= NULL
;
323 sc
->sc_extendedops
= NULL
;
327 sc
->sc_extendedopsbv
= extendedopsbv
;
328 sc
->sc_mask
= controlmask
;
329 sc
->sc_parse
= controlparsefn
;
331 *controlcid
= sc
->sc_cid
;
338 * One-time initialization of internal controls.
341 slap_controls_init( void )
347 for ( i
= 0; control_defs
[i
].sc_oid
!= NULL
; i
++ ) {
348 int *cid
= (int *)(((char *)&slap_cids
) + control_defs
[i
].sc_cid
);
349 rc
= register_supported_control( control_defs
[i
].sc_oid
,
350 control_defs
[i
].sc_mask
, control_defs
[i
].sc_extendedops
,
351 control_defs
[i
].sc_parse
, cid
);
352 if ( rc
!= LDAP_SUCCESS
) break;
359 * Free memory associated with list of supported controls.
362 controls_destroy( void )
364 struct slap_control
*sc
;
366 while ( !LDAP_SLIST_EMPTY(&controls_list
) ) {
367 sc
= LDAP_SLIST_FIRST(&controls_list
);
368 LDAP_SLIST_REMOVE_HEAD(&controls_list
, sc_next
);
370 ch_free( sc
->sc_oid
);
371 if ( sc
->sc_extendedopsbv
!= NULL
) {
372 ber_bvarray_free( sc
->sc_extendedopsbv
);
379 * Format the supportedControl attribute of the root DSE,
380 * detailing which controls are supported by the directory
384 controls_root_dse_info( Entry
*e
)
386 AttributeDescription
*ad_supportedControl
387 = slap_schema
.si_ad_supportedControl
;
388 struct berval vals
[2];
389 struct slap_control
*sc
;
391 vals
[1].bv_val
= NULL
;
394 LDAP_SLIST_FOREACH( sc
, &controls_list
, sc_next
) {
395 if( sc
->sc_mask
& SLAP_CTRL_HIDE
) continue;
397 vals
[0].bv_val
= sc
->sc_oid
;
398 vals
[0].bv_len
= strlen( sc
->sc_oid
);
400 if ( attr_merge( e
, ad_supportedControl
, vals
, NULL
) ) {
409 * Return a list of OIDs and operation masks for supported
410 * controls. Used by SLAPI.
413 get_supported_controls(char ***ctrloidsp
,
414 slap_mask_t
**ctrlmasks
)
419 struct slap_control
*sc
;
423 LDAP_SLIST_FOREACH( sc
, &controls_list
, sc_next
) {
433 oids
= (char **)SLAP_MALLOC( (n
+ 1) * sizeof(char *) );
434 if ( oids
== NULL
) {
435 return LDAP_NO_MEMORY
;
437 masks
= (slap_mask_t
*)SLAP_MALLOC( (n
+ 1) * sizeof(slap_mask_t
) );
438 if ( masks
== NULL
) {
440 return LDAP_NO_MEMORY
;
445 LDAP_SLIST_FOREACH( sc
, &controls_list
, sc_next
) {
446 oids
[n
] = ch_strdup( sc
->sc_oid
);
447 masks
[n
] = sc
->sc_mask
;
460 * Find a control given its OID.
462 static struct slap_control
*
463 find_ctrl( const char *oid
)
465 struct slap_control
*sc
;
467 LDAP_SLIST_FOREACH( sc
, &controls_list
, sc_next
) {
468 if ( strcmp( oid
, sc
->sc_oid
) == 0 ) {
477 slap_find_control_id(
481 struct slap_control
*ctrl
= find_ctrl( oid
);
483 if ( cid
) *cid
= ctrl
->sc_cid
;
486 return LDAP_CONTROL_NOT_FOUND
;
490 slap_global_control( Operation
*op
, const char *oid
, int *cid
)
492 struct slap_control
*ctrl
= find_ctrl( oid
);
494 if ( ctrl
== NULL
) {
495 /* should not be reachable */
496 Debug( LDAP_DEBUG_ANY
,
497 "slap_global_control: unrecognized control: %s\n",
499 return LDAP_CONTROL_NOT_FOUND
;
502 if ( cid
) *cid
= ctrl
->sc_cid
;
504 if ( ( ctrl
->sc_mask
& SLAP_CTRL_GLOBAL
) ||
505 ( ( op
->o_tag
& LDAP_REQ_SEARCH
) &&
506 ( ctrl
->sc_mask
& SLAP_CTRL_GLOBAL_SEARCH
) ) )
508 return LDAP_COMPARE_TRUE
;
512 Debug( LDAP_DEBUG_TRACE
,
513 "slap_global_control: unavailable control: %s\n",
517 return LDAP_COMPARE_FALSE
;
520 void slap_free_ctrls(
522 LDAPControl
**ctrls
)
526 for (i
=0; ctrls
[i
]; i
++) {
527 op
->o_tmpfree(ctrls
[i
], op
->o_tmpmemctx
);
529 op
->o_tmpfree( ctrls
, op
->o_tmpmemctx
);
535 LDAPControl
*control
,
538 struct slap_control
*sc
;
540 sc
= find_ctrl( control
->ldctl_oid
);
542 /* recognized control */
544 switch( op
->o_tag
) {
546 tagmask
= SLAP_CTRL_ADD
;
549 tagmask
= SLAP_CTRL_BIND
;
551 case LDAP_REQ_COMPARE
:
552 tagmask
= SLAP_CTRL_COMPARE
;
554 case LDAP_REQ_DELETE
:
555 tagmask
= SLAP_CTRL_DELETE
;
557 case LDAP_REQ_MODIFY
:
558 tagmask
= SLAP_CTRL_MODIFY
;
560 case LDAP_REQ_RENAME
:
561 tagmask
= SLAP_CTRL_RENAME
;
563 case LDAP_REQ_SEARCH
:
564 tagmask
= SLAP_CTRL_SEARCH
;
566 case LDAP_REQ_UNBIND
:
567 tagmask
= SLAP_CTRL_UNBIND
;
569 case LDAP_REQ_ABANDON
:
570 tagmask
= SLAP_CTRL_ABANDON
;
572 case LDAP_REQ_EXTENDED
:
574 assert( op
->ore_reqoid
.bv_val
!= NULL
);
575 if( sc
->sc_extendedopsbv
!= NULL
) {
577 for( i
=0; !BER_BVISNULL( &sc
->sc_extendedopsbv
[i
] ); i
++ ) {
578 if( bvmatch( &op
->ore_reqoid
,
579 &sc
->sc_extendedopsbv
[i
] ) )
588 *text
= "controls internal error";
592 if (( sc
->sc_mask
& tagmask
) == tagmask
) {
593 /* available extension */
596 if( !sc
->sc_parse
) {
597 *text
= "not yet implemented";
601 rc
= sc
->sc_parse( op
, rs
, control
);
603 assert( rc
!= LDAP_UNAVAILABLE_CRITICAL_EXTENSION
);
607 } else if( control
->ldctl_iscritical
) {
608 /* unavailable CRITICAL control */
609 *text
= "critical extension is unavailable";
610 return LDAP_UNAVAILABLE_CRITICAL_EXTENSION
;
612 } else if( control
->ldctl_iscritical
) {
613 /* unrecognized CRITICAL control */
614 *text
= "critical extension is not recognized";
615 return LDAP_UNAVAILABLE_CRITICAL_EXTENSION
;
630 BerElement
*ber
= op
->o_ber
;
633 len
= ber_pvt_ber_remaining(ber
);
637 rs
->sr_err
= LDAP_SUCCESS
;
641 if(( tag
= ber_peek_tag( ber
, &len
)) != LDAP_TAG_CONTROLS
) {
642 if( tag
== LBER_ERROR
) {
643 rs
->sr_err
= SLAPD_DISCONNECT
;
644 rs
->sr_text
= "unexpected data in PDU";
650 Debug( LDAP_DEBUG_TRACE
,
651 "=> get_ctrls\n", 0, 0, 0 );
653 if( op
->o_protocol
< LDAP_VERSION3
) {
654 rs
->sr_err
= SLAPD_DISCONNECT
;
655 rs
->sr_text
= "controls require LDAPv3";
659 /* one for first control, one for termination */
660 op
->o_ctrls
= op
->o_tmpalloc( 2 * sizeof(LDAPControl
*), op
->o_tmpmemctx
);
663 if( op
->ctrls
== NULL
) {
664 rs
->sr_err
= LDAP_NO_MEMORY
;
665 rs
->sr_text
= "no memory";
670 op
->o_ctrls
[nctrls
] = NULL
;
672 /* step through each element */
673 for( tag
= ber_first_element( ber
, &len
, &opaque
);
675 tag
= ber_next_element( ber
, &len
, opaque
) )
678 LDAPControl
**tctrls
;
680 c
= op
->o_tmpalloc( sizeof(LDAPControl
), op
->o_tmpmemctx
);
681 memset(c
, 0, sizeof(LDAPControl
));
683 /* allocate pointer space for current controls (nctrls)
684 * + this control + extra NULL
686 tctrls
= op
->o_tmprealloc( op
->o_ctrls
,
687 (nctrls
+2) * sizeof(LDAPControl
*), op
->o_tmpmemctx
);
690 if( tctrls
== NULL
) {
692 ldap_controls_free(op
->o_ctrls
);
695 rs
->sr_err
= LDAP_NO_MEMORY
;
696 rs
->sr_text
= "no memory";
700 op
->o_ctrls
= tctrls
;
702 op
->o_ctrls
[nctrls
++] = c
;
703 op
->o_ctrls
[nctrls
] = NULL
;
705 tag
= ber_scanf( ber
, "{m" /*}*/, &bv
);
706 c
->ldctl_oid
= bv
.bv_val
;
708 if( tag
== LBER_ERROR
) {
709 Debug( LDAP_DEBUG_TRACE
, "=> get_ctrls: get oid failed.\n",
712 slap_free_ctrls( op
, op
->o_ctrls
);
714 rs
->sr_err
= SLAPD_DISCONNECT
;
715 rs
->sr_text
= "decoding controls error";
718 } else if( c
->ldctl_oid
== NULL
) {
719 Debug( LDAP_DEBUG_TRACE
,
720 "get_ctrls: conn %lu got emtpy OID.\n",
721 op
->o_connid
, 0, 0 );
723 slap_free_ctrls( op
, op
->o_ctrls
);
725 rs
->sr_err
= LDAP_PROTOCOL_ERROR
;
726 rs
->sr_text
= "OID field is empty";
730 tag
= ber_peek_tag( ber
, &len
);
732 if( tag
== LBER_BOOLEAN
) {
734 tag
= ber_scanf( ber
, "b", &crit
);
736 if( tag
== LBER_ERROR
) {
737 Debug( LDAP_DEBUG_TRACE
, "=> get_ctrls: get crit failed.\n",
739 slap_free_ctrls( op
, op
->o_ctrls
);
741 rs
->sr_err
= SLAPD_DISCONNECT
;
742 rs
->sr_text
= "decoding controls error";
746 c
->ldctl_iscritical
= (crit
!= 0);
747 tag
= ber_peek_tag( ber
, &len
);
750 if( tag
== LBER_OCTETSTRING
) {
751 tag
= ber_scanf( ber
, "m", &c
->ldctl_value
);
753 if( tag
== LBER_ERROR
) {
754 Debug( LDAP_DEBUG_TRACE
, "=> get_ctrls: conn %lu: "
755 "%s (%scritical): get value failed.\n",
756 op
->o_connid
, c
->ldctl_oid
,
757 c
->ldctl_iscritical
? "" : "non" );
758 slap_free_ctrls( op
, op
->o_ctrls
);
760 rs
->sr_err
= SLAPD_DISCONNECT
;
761 rs
->sr_text
= "decoding controls error";
766 Debug( LDAP_DEBUG_TRACE
,
767 "=> get_ctrls: oid=\"%s\" (%scritical)\n",
768 c
->ldctl_oid
, c
->ldctl_iscritical
? "" : "non", 0 );
770 rs
->sr_err
= slap_parse_ctrl( op
, rs
, c
, &rs
->sr_text
);
771 if ( rs
->sr_err
!= LDAP_SUCCESS
) {
777 Debug( LDAP_DEBUG_TRACE
,
778 "<= get_ctrls: n=%d rc=%d err=\"%s\"\n",
779 nctrls
, rs
->sr_err
, rs
->sr_text
? rs
->sr_text
: "");
781 if( sendres
&& rs
->sr_err
!= LDAP_SUCCESS
) {
782 if( rs
->sr_err
== SLAPD_DISCONNECT
) {
783 rs
->sr_err
= LDAP_PROTOCOL_ERROR
;
784 send_ldap_disconnect( op
, rs
);
785 rs
->sr_err
= SLAPD_DISCONNECT
;
787 send_ldap_result( op
, rs
);
799 BI_chk_controls fnc
)
803 switch ( op
->o_ctrlflag
[ ctrl
] ) {
804 case SLAP_CONTROL_NONCRITICAL
:
805 for ( i
= 0, j
= -1; op
->o_ctrls
[ i
] != NULL
; i
++ ) {
806 if ( strcmp( op
->o_ctrls
[ i
]->ldctl_oid
,
807 slap_known_controls
[ ctrl
- 1 ] ) == 0 )
814 rs
->sr_err
= LDAP_OTHER
;
822 op
->o_tmpfree( op
->o_ctrls
[ j
], op
->o_tmpmemctx
);
825 AC_MEMCPY( &op
->o_ctrls
[ j
], &op
->o_ctrls
[ j
+ 1 ],
826 ( i
- j
) * sizeof( LDAPControl
* ) );
829 op
->o_tmpfree( op
->o_ctrls
, op
->o_tmpmemctx
);
833 op
->o_ctrlflag
[ ctrl
] = SLAP_CONTROL_IGNORED
;
835 Debug( LDAP_DEBUG_ANY
, "%s: "
836 "non-critical control \"%s\" not supported; stripped.\n",
837 op
->o_log_prefix
, slap_known_controls
[ ctrl
], 0 );
840 case SLAP_CONTROL_IGNORED
:
841 case SLAP_CONTROL_NONE
:
842 rs
->sr_err
= SLAP_CB_CONTINUE
;
845 case SLAP_CONTROL_CRITICAL
:
846 rs
->sr_err
= LDAP_UNAVAILABLE_CRITICAL_EXTENSION
;
850 Debug( LDAP_DEBUG_ANY
, "%s: "
851 "critical control \"%s\" not supported.\n",
852 op
->o_log_prefix
, slap_known_controls
[ ctrl
], 0 );
856 /* handle all cases! */
863 static int parseDontUseCopy (
868 if ( op
->o_dontUseCopy
!= SLAP_CONTROL_NONE
) {
869 rs
->sr_text
= "dontUseCopy control specified multiple times";
870 return LDAP_PROTOCOL_ERROR
;
873 if ( !BER_BVISNULL( &ctrl
->ldctl_value
)) {
874 rs
->sr_text
= "dontUseCopy control value not absent";
875 return LDAP_PROTOCOL_ERROR
;
878 if ( !ctrl
->ldctl_iscritical
) {
879 rs
->sr_text
= "dontUseCopy criticality of FALSE not allowed";
880 return LDAP_PROTOCOL_ERROR
;
883 op
->o_dontUseCopy
= SLAP_CONTROL_CRITICAL
;
887 static int parseRelax (
892 if ( op
->o_relax
!= SLAP_CONTROL_NONE
) {
893 rs
->sr_text
= "relax control specified multiple times";
894 return LDAP_PROTOCOL_ERROR
;
897 if ( !BER_BVISNULL( &ctrl
->ldctl_value
)) {
898 rs
->sr_text
= "relax control value not absent";
899 return LDAP_PROTOCOL_ERROR
;
902 op
->o_relax
= ctrl
->ldctl_iscritical
903 ? SLAP_CONTROL_CRITICAL
904 : SLAP_CONTROL_NONCRITICAL
;
909 static int parseManageDSAit (
914 if ( op
->o_managedsait
!= SLAP_CONTROL_NONE
) {
915 rs
->sr_text
= "manageDSAit control specified multiple times";
916 return LDAP_PROTOCOL_ERROR
;
919 if ( !BER_BVISNULL( &ctrl
->ldctl_value
)) {
920 rs
->sr_text
= "manageDSAit control value not absent";
921 return LDAP_PROTOCOL_ERROR
;
924 op
->o_managedsait
= ctrl
->ldctl_iscritical
925 ? SLAP_CONTROL_CRITICAL
926 : SLAP_CONTROL_NONCRITICAL
;
931 static int parseProxyAuthz (
937 struct berval dn
= BER_BVNULL
;
939 if ( op
->o_proxy_authz
!= SLAP_CONTROL_NONE
) {
940 rs
->sr_text
= "proxy authorization control specified multiple times";
941 return LDAP_PROTOCOL_ERROR
;
944 if ( BER_BVISNULL( &ctrl
->ldctl_value
)) {
945 rs
->sr_text
= "proxy authorization control value absent";
946 return LDAP_PROTOCOL_ERROR
;
949 if ( !( global_allows
& SLAP_ALLOW_PROXY_AUTHZ_ANON
)
950 && BER_BVISEMPTY( &op
->o_ndn
) )
952 rs
->sr_text
= "anonymous proxied authorization not allowed";
953 return LDAP_PROXIED_AUTHORIZATION_DENIED
;
956 op
->o_proxy_authz
= ctrl
->ldctl_iscritical
957 ? SLAP_CONTROL_CRITICAL
958 : SLAP_CONTROL_NONCRITICAL
;
960 Debug( LDAP_DEBUG_ARGS
,
961 "parseProxyAuthz: conn %lu authzid=\"%s\"\n",
963 ctrl
->ldctl_value
.bv_len
? ctrl
->ldctl_value
.bv_val
: "anonymous",
966 if ( BER_BVISEMPTY( &ctrl
->ldctl_value
)) {
967 Debug( LDAP_DEBUG_TRACE
,
968 "parseProxyAuthz: conn=%lu anonymous\n",
969 op
->o_connid
, 0, 0 );
972 if ( !BER_BVISNULL( &op
->o_ndn
) ) {
973 op
->o_ndn
.bv_val
[ 0 ] = '\0';
975 op
->o_ndn
.bv_len
= 0;
977 if ( !BER_BVISNULL( &op
->o_dn
) ) {
978 op
->o_dn
.bv_val
[ 0 ] = '\0';
985 rc
= slap_sasl_getdn( op
->o_conn
, op
, &ctrl
->ldctl_value
,
986 NULL
, &dn
, SLAP_GETDN_AUTHZID
);
988 /* FIXME: empty DN in proxyAuthz control should be legal... */
989 if( rc
!= LDAP_SUCCESS
/* || !dn.bv_len */ ) {
991 ch_free( dn
.bv_val
);
993 rs
->sr_text
= "authzId mapping failed";
994 return LDAP_PROXIED_AUTHORIZATION_DENIED
;
997 Debug( LDAP_DEBUG_TRACE
,
998 "parseProxyAuthz: conn=%lu \"%s\"\n",
1000 dn
.bv_len
? dn
.bv_val
: "(NULL)", 0 );
1002 rc
= slap_sasl_authorized( op
, &op
->o_ndn
, &dn
);
1005 ch_free( dn
.bv_val
);
1006 rs
->sr_text
= "not authorized to assume identity";
1007 return LDAP_PROXIED_AUTHORIZATION_DENIED
;
1010 ch_free( op
->o_ndn
.bv_val
);
1011 ch_free( op
->o_dn
.bv_val
);
1014 * NOTE: since slap_sasl_getdn() returns a normalized dn,
1015 * from now on op->o_dn is normalized
1018 ber_dupbv( &op
->o_dn
, &dn
);
1020 Statslog( LDAP_DEBUG_STATS
, "%s PROXYAUTHZ dn=\"%s\"\n",
1021 op
->o_log_prefix
, dn
.bv_val
, 0, 0, 0 );
1023 return LDAP_SUCCESS
;
1026 static int parseNoOp (
1031 if ( op
->o_noop
!= SLAP_CONTROL_NONE
) {
1032 rs
->sr_text
= "noop control specified multiple times";
1033 return LDAP_PROTOCOL_ERROR
;
1036 if ( !BER_BVISNULL( &ctrl
->ldctl_value
) ) {
1037 rs
->sr_text
= "noop control value not empty";
1038 return LDAP_PROTOCOL_ERROR
;
1041 op
->o_noop
= ctrl
->ldctl_iscritical
1042 ? SLAP_CONTROL_CRITICAL
1043 : SLAP_CONTROL_NONCRITICAL
;
1045 return LDAP_SUCCESS
;
1048 static int parsePagedResults (
1053 BerElementBuffer berbuf
;
1054 BerElement
*ber
= (BerElement
*)&berbuf
;
1055 struct berval cookie
;
1056 PagedResultsState
*ps
;
1057 int rc
= LDAP_SUCCESS
;
1061 if ( op
->o_pagedresults
!= SLAP_CONTROL_NONE
) {
1062 rs
->sr_text
= "paged results control specified multiple times";
1063 return LDAP_PROTOCOL_ERROR
;
1066 if ( BER_BVISNULL( &ctrl
->ldctl_value
) ) {
1067 rs
->sr_text
= "paged results control value is absent";
1068 return LDAP_PROTOCOL_ERROR
;
1071 if ( BER_BVISEMPTY( &ctrl
->ldctl_value
) ) {
1072 rs
->sr_text
= "paged results control value is empty";
1073 return LDAP_PROTOCOL_ERROR
;
1076 /* Parse the control value
1077 * realSearchControlValue ::= SEQUENCE {
1078 * size INTEGER (0..maxInt),
1079 * -- requested page size from client
1080 * -- result set size estimate from server
1081 * cookie OCTET STRING
1084 ber_init2( ber
, &ctrl
->ldctl_value
, LBER_USE_DER
);
1086 tag
= ber_scanf( ber
, "{im}", &size
, &cookie
);
1088 if ( tag
== LBER_ERROR
) {
1089 rs
->sr_text
= "paged results control could not be decoded";
1090 rc
= LDAP_PROTOCOL_ERROR
;
1095 rs
->sr_text
= "paged results control size invalid";
1096 rc
= LDAP_PROTOCOL_ERROR
;
1100 ps
= op
->o_tmpalloc( sizeof(PagedResultsState
), op
->o_tmpmemctx
);
1101 *ps
= op
->o_conn
->c_pagedresults_state
;
1103 ps
->ps_cookieval
= cookie
;
1104 op
->o_pagedresults_state
= ps
;
1105 if ( !cookie
.bv_len
) {
1110 /* NOTE: according to RFC 2696 3.:
1112 If the page size is greater than or equal to the sizeLimit value, the
1113 server should ignore the control as the request can be satisfied in a
1116 * NOTE: this assumes that the op->ors_slimit be set
1117 * before the controls are parsed.
1120 if ( op
->ors_slimit
> 0 && size
>= op
->ors_slimit
) {
1121 op
->o_pagedresults
= SLAP_CONTROL_IGNORED
;
1123 } else if ( ctrl
->ldctl_iscritical
) {
1124 op
->o_pagedresults
= SLAP_CONTROL_CRITICAL
;
1127 op
->o_pagedresults
= SLAP_CONTROL_NONCRITICAL
;
1134 #ifdef SLAP_CONTROL_X_SORTEDRESULTS
1135 static int parseSortedResults (
1140 int rc
= LDAP_SUCCESS
;
1142 if ( op
->o_sortedresults
!= SLAP_CONTROL_NONE
) {
1143 rs
->sr_text
= "sorted results control specified multiple times";
1144 return LDAP_PROTOCOL_ERROR
;
1147 if ( BER_BVISNULL( &ctrl
->ldctl_value
) ) {
1148 rs
->sr_text
= "sorted results control value is absent";
1149 return LDAP_PROTOCOL_ERROR
;
1152 if ( BER_BVISEMPTY( &ctrl
->ldctl_value
) ) {
1153 rs
->sr_text
= "sorted results control value is empty";
1154 return LDAP_PROTOCOL_ERROR
;
1157 /* blow off parsing the value */
1159 op
->o_sortedresults
= ctrl
->ldctl_iscritical
1160 ? SLAP_CONTROL_CRITICAL
1161 : SLAP_CONTROL_NONCRITICAL
;
1167 static int parseAssert (
1173 struct berval fstr
= BER_BVNULL
;
1175 if ( op
->o_assert
!= SLAP_CONTROL_NONE
) {
1176 rs
->sr_text
= "assert control specified multiple times";
1177 return LDAP_PROTOCOL_ERROR
;
1180 if ( BER_BVISNULL( &ctrl
->ldctl_value
)) {
1181 rs
->sr_text
= "assert control value is absent";
1182 return LDAP_PROTOCOL_ERROR
;
1185 if ( BER_BVISEMPTY( &ctrl
->ldctl_value
)) {
1186 rs
->sr_text
= "assert control value is empty";
1187 return LDAP_PROTOCOL_ERROR
;
1190 ber
= ber_init( &(ctrl
->ldctl_value
) );
1192 rs
->sr_text
= "assert control: internal error";
1196 rs
->sr_err
= get_filter( op
, ber
, (Filter
**)&(op
->o_assertion
),
1198 (void) ber_free( ber
, 1 );
1199 if( rs
->sr_err
!= LDAP_SUCCESS
) {
1200 if( rs
->sr_err
== SLAPD_DISCONNECT
) {
1201 rs
->sr_err
= LDAP_PROTOCOL_ERROR
;
1202 send_ldap_disconnect( op
, rs
);
1203 rs
->sr_err
= SLAPD_DISCONNECT
;
1205 send_ldap_result( op
, rs
);
1207 if( op
->o_assertion
!= NULL
) {
1208 filter_free_x( op
, op
->o_assertion
);
1214 filter2bv_x( op
, op
->o_assertion
, &fstr
);
1216 Debug( LDAP_DEBUG_ARGS
, "parseAssert: conn %ld assert: %s\n",
1217 op
->o_connid
, fstr
.bv_len
? fstr
.bv_val
: "empty" , 0 );
1218 op
->o_tmpfree( fstr
.bv_val
, op
->o_tmpmemctx
);
1221 op
->o_assert
= ctrl
->ldctl_iscritical
1222 ? SLAP_CONTROL_CRITICAL
1223 : SLAP_CONTROL_NONCRITICAL
;
1225 rs
->sr_err
= LDAP_SUCCESS
;
1226 return LDAP_SUCCESS
;
1229 static int parsePreRead (
1234 ber_len_t siz
, off
, i
;
1235 AttributeName
*an
= NULL
;
1238 if ( op
->o_preread
!= SLAP_CONTROL_NONE
) {
1239 rs
->sr_text
= "preread control specified multiple times";
1240 return LDAP_PROTOCOL_ERROR
;
1243 if ( BER_BVISNULL( &ctrl
->ldctl_value
)) {
1244 rs
->sr_text
= "preread control value is absent";
1245 return LDAP_PROTOCOL_ERROR
;
1248 if ( BER_BVISEMPTY( &ctrl
->ldctl_value
)) {
1249 rs
->sr_text
= "preread control value is empty";
1250 return LDAP_PROTOCOL_ERROR
;
1254 if ( op
->o_txnSpec
) { /* temporary limitation */
1255 rs
->sr_text
= "cannot perform pre-read in transaction";
1256 return LDAP_UNWILLING_TO_PERFORM
;
1260 ber
= ber_init( &(ctrl
->ldctl_value
) );
1262 rs
->sr_text
= "preread control: internal error";
1266 rs
->sr_err
= LDAP_SUCCESS
;
1268 siz
= sizeof( AttributeName
);
1269 off
= offsetof( AttributeName
, an_name
);
1270 if ( ber_scanf( ber
, "{M}", &an
, &siz
, off
) == LBER_ERROR
) {
1271 rs
->sr_text
= "preread control: decoding error";
1272 rs
->sr_err
= LDAP_PROTOCOL_ERROR
;
1276 for( i
=0; i
<siz
; i
++ ) {
1277 const char *dummy
= NULL
;
1279 an
[i
].an_desc
= NULL
;
1281 an
[i
].an_oc_exclude
= 0;
1282 rs
->sr_err
= slap_bv2ad( &an
[i
].an_name
, &an
[i
].an_desc
, &dummy
);
1283 if ( rs
->sr_err
!= LDAP_SUCCESS
&& ctrl
->ldctl_iscritical
) {
1286 : "postread control: unknown attributeType";
1291 op
->o_preread
= ctrl
->ldctl_iscritical
1292 ? SLAP_CONTROL_CRITICAL
1293 : SLAP_CONTROL_NONCRITICAL
;
1295 op
->o_preread_attrs
= an
;
1298 (void) ber_free( ber
, 1 );
1302 static int parsePostRead (
1307 ber_len_t siz
, off
, i
;
1308 AttributeName
*an
= NULL
;
1311 if ( op
->o_postread
!= SLAP_CONTROL_NONE
) {
1312 rs
->sr_text
= "postread control specified multiple times";
1313 return LDAP_PROTOCOL_ERROR
;
1316 if ( BER_BVISNULL( &ctrl
->ldctl_value
)) {
1317 rs
->sr_text
= "postread control value is absent";
1318 return LDAP_PROTOCOL_ERROR
;
1321 if ( BER_BVISEMPTY( &ctrl
->ldctl_value
)) {
1322 rs
->sr_text
= "postread control value is empty";
1323 return LDAP_PROTOCOL_ERROR
;
1327 if ( op
->o_txnSpec
) { /* temporary limitation */
1328 rs
->sr_text
= "cannot perform post-read in transaction";
1329 return LDAP_UNWILLING_TO_PERFORM
;
1333 ber
= ber_init( &(ctrl
->ldctl_value
) );
1335 rs
->sr_text
= "postread control: internal error";
1339 rs
->sr_err
= LDAP_SUCCESS
;
1340 siz
= sizeof( AttributeName
);
1341 off
= offsetof( AttributeName
, an_name
);
1342 if ( ber_scanf( ber
, "{M}", &an
, &siz
, off
) == LBER_ERROR
) {
1343 rs
->sr_text
= "postread control: decoding error";
1344 rs
->sr_err
= LDAP_PROTOCOL_ERROR
;
1348 for ( i
= 0; i
< siz
; i
++ ) {
1349 const char *dummy
= NULL
;
1352 an
[i
].an_desc
= NULL
;
1354 an
[i
].an_oc_exclude
= 0;
1355 rc
= slap_bv2ad( &an
[i
].an_name
, &an
[i
].an_desc
, &dummy
);
1356 if ( rc
!= LDAP_SUCCESS
) {
1358 static struct berval special_attrs
[] = {
1359 BER_BVC( LDAP_NO_ATTRS
),
1360 BER_BVC( LDAP_ALL_USER_ATTRIBUTES
),
1361 BER_BVC( LDAP_ALL_OPERATIONAL_ATTRIBUTES
),
1365 /* deal with special attribute types */
1366 for ( i
= 0; !BER_BVISNULL( &special_attrs
[ i
] ); i
++ ) {
1367 if ( bvmatch( &an
[i
].an_name
, &special_attrs
[ i
] ) ) {
1372 if ( BER_BVISNULL( &special_attrs
[ i
] ) && ctrl
->ldctl_iscritical
) {
1376 : "postread control: unknown attributeType";
1382 op
->o_postread
= ctrl
->ldctl_iscritical
1383 ? SLAP_CONTROL_CRITICAL
1384 : SLAP_CONTROL_NONCRITICAL
;
1386 op
->o_postread_attrs
= an
;
1389 (void) ber_free( ber
, 1 );
1393 static int parseValuesReturnFilter (
1399 struct berval fstr
= BER_BVNULL
;
1401 if ( op
->o_valuesreturnfilter
!= SLAP_CONTROL_NONE
) {
1402 rs
->sr_text
= "valuesReturnFilter control specified multiple times";
1403 return LDAP_PROTOCOL_ERROR
;
1406 if ( BER_BVISNULL( &ctrl
->ldctl_value
)) {
1407 rs
->sr_text
= "valuesReturnFilter control value is absent";
1408 return LDAP_PROTOCOL_ERROR
;
1411 if ( BER_BVISEMPTY( &ctrl
->ldctl_value
)) {
1412 rs
->sr_text
= "valuesReturnFilter control value is empty";
1413 return LDAP_PROTOCOL_ERROR
;
1416 ber
= ber_init( &(ctrl
->ldctl_value
) );
1418 rs
->sr_text
= "internal error";
1422 rs
->sr_err
= get_vrFilter( op
, ber
,
1423 (ValuesReturnFilter
**)&(op
->o_vrFilter
), &rs
->sr_text
);
1425 (void) ber_free( ber
, 1 );
1427 if( rs
->sr_err
!= LDAP_SUCCESS
) {
1428 if( rs
->sr_err
== SLAPD_DISCONNECT
) {
1429 rs
->sr_err
= LDAP_PROTOCOL_ERROR
;
1430 send_ldap_disconnect( op
, rs
);
1431 rs
->sr_err
= SLAPD_DISCONNECT
;
1433 send_ldap_result( op
, rs
);
1435 if( op
->o_vrFilter
!= NULL
) vrFilter_free( op
, op
->o_vrFilter
);
1439 vrFilter2bv( op
, op
->o_vrFilter
, &fstr
);
1442 Debug( LDAP_DEBUG_ARGS
, " vrFilter: %s\n",
1443 fstr
.bv_len
? fstr
.bv_val
: "empty", 0, 0 );
1444 op
->o_tmpfree( fstr
.bv_val
, op
->o_tmpmemctx
);
1447 op
->o_valuesreturnfilter
= ctrl
->ldctl_iscritical
1448 ? SLAP_CONTROL_CRITICAL
1449 : SLAP_CONTROL_NONCRITICAL
;
1451 rs
->sr_err
= LDAP_SUCCESS
;
1452 return LDAP_SUCCESS
;
1455 static int parseSubentries (
1460 if ( op
->o_subentries
!= SLAP_CONTROL_NONE
) {
1461 rs
->sr_text
= "subentries control specified multiple times";
1462 return LDAP_PROTOCOL_ERROR
;
1465 /* FIXME: should use BER library */
1466 if( ( ctrl
->ldctl_value
.bv_len
!= 3 )
1467 || ( ctrl
->ldctl_value
.bv_val
[0] != 0x01 )
1468 || ( ctrl
->ldctl_value
.bv_val
[1] != 0x01 ))
1470 rs
->sr_text
= "subentries control value encoding is bogus";
1471 return LDAP_PROTOCOL_ERROR
;
1474 op
->o_subentries
= ctrl
->ldctl_iscritical
1475 ? SLAP_CONTROL_CRITICAL
1476 : SLAP_CONTROL_NONCRITICAL
;
1478 if (ctrl
->ldctl_value
.bv_val
[2]) {
1479 set_subentries_visibility( op
);
1482 return LDAP_SUCCESS
;
1485 static int parsePermissiveModify (
1490 if ( op
->o_permissive_modify
!= SLAP_CONTROL_NONE
) {
1491 rs
->sr_text
= "permissiveModify control specified multiple times";
1492 return LDAP_PROTOCOL_ERROR
;
1495 if ( BER_BVISNULL( &ctrl
->ldctl_value
)) {
1496 rs
->sr_text
= "permissiveModify control value not absent";
1497 return LDAP_PROTOCOL_ERROR
;
1500 op
->o_permissive_modify
= ctrl
->ldctl_iscritical
1501 ? SLAP_CONTROL_CRITICAL
1502 : SLAP_CONTROL_NONCRITICAL
;
1504 return LDAP_SUCCESS
;
1507 static int parseDomainScope (
1512 if ( op
->o_domain_scope
!= SLAP_CONTROL_NONE
) {
1513 rs
->sr_text
= "domainScope control specified multiple times";
1514 return LDAP_PROTOCOL_ERROR
;
1517 if ( BER_BVISNULL( &ctrl
->ldctl_value
)) {
1518 rs
->sr_text
= "domainScope control value not empty";
1519 return LDAP_PROTOCOL_ERROR
;
1522 op
->o_domain_scope
= ctrl
->ldctl_iscritical
1523 ? SLAP_CONTROL_CRITICAL
1524 : SLAP_CONTROL_NONCRITICAL
;
1526 return LDAP_SUCCESS
;
1529 #ifdef SLAP_CONTROL_X_TREE_DELETE
1530 static int parseTreeDelete (
1535 if ( op
->o_tree_delete
!= SLAP_CONTROL_NONE
) {
1536 rs
->sr_text
= "treeDelete control specified multiple times";
1537 return LDAP_PROTOCOL_ERROR
;
1540 if ( !BER_BVISNULL( &ctrl
->ldctl_value
)) {
1541 rs
->sr_text
= "treeDelete control value not absent";
1542 return LDAP_PROTOCOL_ERROR
;
1545 op
->o_tree_delete
= ctrl
->ldctl_iscritical
1546 ? SLAP_CONTROL_CRITICAL
1547 : SLAP_CONTROL_NONCRITICAL
;
1549 return LDAP_SUCCESS
;
1553 static int parseSearchOptions (
1559 ber_int_t search_flags
;
1562 if ( BER_BVISNULL( &ctrl
->ldctl_value
)) {
1563 rs
->sr_text
= "searchOptions control value is absent";
1564 return LDAP_PROTOCOL_ERROR
;
1567 if ( BER_BVISEMPTY( &ctrl
->ldctl_value
)) {
1568 rs
->sr_text
= "searchOptions control value is empty";
1569 return LDAP_PROTOCOL_ERROR
;
1572 ber
= ber_init( &ctrl
->ldctl_value
);
1574 rs
->sr_text
= "internal error";
1578 tag
= ber_scanf( ber
, "{i}", &search_flags
);
1579 (void) ber_free( ber
, 1 );
1581 if ( tag
== LBER_ERROR
) {
1582 rs
->sr_text
= "searchOptions control decoding error";
1583 return LDAP_PROTOCOL_ERROR
;
1586 if ( search_flags
& LDAP_SEARCH_FLAG_DOMAIN_SCOPE
) {
1587 if ( op
->o_domain_scope
!= SLAP_CONTROL_NONE
) {
1588 rs
->sr_text
= "searchOptions control specified multiple times "
1589 "or with domainScope control";
1590 return LDAP_PROTOCOL_ERROR
;
1593 op
->o_domain_scope
= ctrl
->ldctl_iscritical
1594 ? SLAP_CONTROL_CRITICAL
1595 : SLAP_CONTROL_NONCRITICAL
;
1598 if ( search_flags
& ~(LDAP_SEARCH_FLAG_DOMAIN_SCOPE
) ) {
1599 /* Other search flags not recognised so far,
1601 * LDAP_SEARCH_FLAG_PHANTOM_ROOM
1603 rs
->sr_text
= "searchOptions contained unrecognized flag";
1604 return LDAP_UNWILLING_TO_PERFORM
;
1607 return LDAP_SUCCESS
;
1610 #ifdef SLAP_CONTROL_X_SESSION_TRACKING
1611 struct berval session_tracking_formats
[] = {
1612 BER_BVC( LDAP_CONTROL_X_SESSION_TRACKING_RADIUS_ACCT_SESSION_ID
),
1613 BER_BVC( "RADIUS-Acct-Session-Id" ),
1614 BER_BVC( LDAP_CONTROL_X_SESSION_TRACKING_RADIUS_ACCT_MULTI_SESSION_ID
),
1615 BER_BVC( "RADIUS-Acct-Multi-Session-Id" ),
1616 BER_BVC( LDAP_CONTROL_X_SESSION_TRACKING_USERNAME
),
1617 BER_BVC( "USERNAME" ),
1622 static int parseSessionTracking(
1632 struct berval sessionSourceIp
= BER_BVNULL
,
1633 sessionSourceName
= BER_BVNULL
,
1634 formatOID
= BER_BVNULL
,
1635 sessionTrackingIdentifier
= BER_BVNULL
;
1637 size_t st_len
, st_pos
;
1639 if ( ctrl
->ldctl_iscritical
) {
1640 rs
->sr_text
= "sessionTracking criticality is TRUE";
1641 return LDAP_PROTOCOL_ERROR
;
1644 if ( BER_BVISNULL( &ctrl
->ldctl_value
) ) {
1645 rs
->sr_text
= "sessionTracking control value is absent";
1646 return LDAP_PROTOCOL_ERROR
;
1649 if ( BER_BVISEMPTY( &ctrl
->ldctl_value
) ) {
1650 rs
->sr_text
= "sessionTracking control value is empty";
1651 return LDAP_PROTOCOL_ERROR
;
1654 /* TODO: add the capability to determine if a client is allowed
1655 * to use this control, based on identity, ip and so */
1657 ber
= ber_init( &ctrl
->ldctl_value
);
1658 if ( ber
== NULL
) {
1659 rs
->sr_text
= "internal error";
1663 tag
= ber_skip_tag( ber
, &len
);
1664 if ( tag
!= LBER_SEQUENCE
) {
1669 /* sessionSourceIp */
1670 tag
= ber_peek_tag( ber
, &len
);
1671 if ( tag
== LBER_DEFAULT
) {
1677 tag
= ber_skip_tag( ber
, &len
);
1679 } else if ( len
> 128 ) {
1680 rs
->sr_text
= "sessionTracking.sessionSourceIp too long";
1681 rs
->sr_err
= LDAP_PROTOCOL_ERROR
;
1685 tag
= ber_scanf( ber
, "m", &sessionSourceIp
);
1688 if ( ldif_is_not_printable( sessionSourceIp
.bv_val
, sessionSourceIp
.bv_len
) ) {
1689 BER_BVZERO( &sessionSourceIp
);
1692 /* sessionSourceName */
1693 tag
= ber_peek_tag( ber
, &len
);
1694 if ( tag
== LBER_DEFAULT
) {
1700 tag
= ber_skip_tag( ber
, &len
);
1702 } else if ( len
> 65536 ) {
1703 rs
->sr_text
= "sessionTracking.sessionSourceName too long";
1704 rs
->sr_err
= LDAP_PROTOCOL_ERROR
;
1708 tag
= ber_scanf( ber
, "m", &sessionSourceName
);
1711 if ( ldif_is_not_printable( sessionSourceName
.bv_val
, sessionSourceName
.bv_len
) ) {
1712 BER_BVZERO( &sessionSourceName
);
1716 tag
= ber_peek_tag( ber
, &len
);
1717 if ( tag
== LBER_DEFAULT
) {
1723 rs
->sr_text
= "sessionTracking.formatOID empty";
1724 rs
->sr_err
= LDAP_PROTOCOL_ERROR
;
1727 } else if ( len
> 1024 ) {
1728 rs
->sr_text
= "sessionTracking.formatOID too long";
1729 rs
->sr_err
= LDAP_PROTOCOL_ERROR
;
1733 tag
= ber_scanf( ber
, "m", &formatOID
);
1736 rc
= numericoidValidate( NULL
, &formatOID
);
1737 if ( rc
!= LDAP_SUCCESS
) {
1738 rs
->sr_text
= "sessionTracking.formatOID invalid";
1742 for ( i
= 0; !BER_BVISNULL( &session_tracking_formats
[ i
] ); i
+= 2 )
1744 if ( bvmatch( &formatOID
, &session_tracking_formats
[ i
] ) ) {
1745 formatOID
= session_tracking_formats
[ i
+ 1 ];
1750 /* sessionTrackingIdentifier */
1751 tag
= ber_peek_tag( ber
, &len
);
1752 if ( tag
== LBER_DEFAULT
) {
1758 tag
= ber_skip_tag( ber
, &len
);
1761 /* note: should not be more than 65536... */
1762 tag
= ber_scanf( ber
, "m", &sessionTrackingIdentifier
);
1763 if ( ldif_is_not_printable( sessionTrackingIdentifier
.bv_val
, sessionTrackingIdentifier
.bv_len
) ) {
1764 /* we want the OID printed, at least */
1765 BER_BVSTR( &sessionTrackingIdentifier
, "" );
1770 tag
= ber_skip_tag( ber
, &len
);
1771 if ( tag
!= LBER_DEFAULT
|| len
!= 0 ) {
1778 if ( !BER_BVISNULL( &sessionSourceIp
) ) {
1779 st_len
+= STRLENOF( "IP=" ) + sessionSourceIp
.bv_len
;
1781 if ( !BER_BVISNULL( &sessionSourceName
) ) {
1782 if ( st_len
) st_len
++;
1783 st_len
+= STRLENOF( "NAME=" ) + sessionSourceName
.bv_len
;
1785 if ( !BER_BVISNULL( &sessionTrackingIdentifier
) ) {
1786 if ( st_len
) st_len
++;
1787 st_len
+= formatOID
.bv_len
+ STRLENOF( "=" )
1788 + sessionTrackingIdentifier
.bv_len
;
1791 if ( st_len
== 0 ) {
1795 st_len
+= STRLENOF( " []" );
1796 st_pos
= strlen( op
->o_log_prefix
);
1798 if ( sizeof( op
->o_log_prefix
) - st_pos
> st_len
) {
1799 char *ptr
= &op
->o_log_prefix
[ st_pos
];
1801 ptr
= lutil_strcopy( ptr
, " [" /*]*/ );
1804 if ( !BER_BVISNULL( &sessionSourceIp
) ) {
1805 ptr
= lutil_strcopy( ptr
, "IP=" );
1806 ptr
= lutil_strcopy( ptr
, sessionSourceIp
.bv_val
);
1810 if ( !BER_BVISNULL( &sessionSourceName
) ) {
1811 if ( st_len
) *ptr
++ = ' ';
1812 ptr
= lutil_strcopy( ptr
, "NAME=" );
1813 ptr
= lutil_strcopy( ptr
, sessionSourceName
.bv_val
);
1817 if ( !BER_BVISNULL( &sessionTrackingIdentifier
) ) {
1818 if ( st_len
) *ptr
++ = ' ';
1819 ptr
= lutil_strcopy( ptr
, formatOID
.bv_val
);
1821 ptr
= lutil_strcopy( ptr
, sessionTrackingIdentifier
.bv_val
);
1829 (void)ber_free( ber
, 1 );
1831 if ( tag
== LBER_ERROR
) {
1832 rs
->sr_text
= "sessionTracking control decoding error";
1833 return LDAP_PROTOCOL_ERROR
;
1841 slap_ctrl_session_tracking_add(
1845 struct berval
*name
,
1849 BerElementBuffer berbuf
;
1850 BerElement
*ber
= (BerElement
*)&berbuf
;
1852 static struct berval oid
= BER_BVC( LDAP_CONTROL_X_SESSION_TRACKING_USERNAME
);
1854 assert( ctrl
!= NULL
);
1856 ber_init2( ber
, NULL
, LBER_USE_DER
);
1858 ber_printf( ber
, "{OOOO}", ip
, name
, &oid
, id
);
1860 if ( ber_flatten2( ber
, &ctrl
->ldctl_value
, 0 ) == -1 ) {
1861 rs
->sr_err
= LDAP_OTHER
;
1865 ctrl
->ldctl_oid
= LDAP_CONTROL_X_SESSION_TRACKING
;
1866 ctrl
->ldctl_iscritical
= 0;
1868 rs
->sr_err
= LDAP_SUCCESS
;
1875 slap_ctrl_session_tracking_request_add( Operation
*op
, SlapReply
*rs
, LDAPControl
*ctrl
)
1877 static struct berval bv_unknown
= BER_BVC( SLAP_STRING_UNKNOWN
);
1878 struct berval ip
= BER_BVNULL
,
1882 if ( !BER_BVISNULL( &op
->o_conn
->c_peer_name
) &&
1883 memcmp( op
->o_conn
->c_peer_name
.bv_val
, "IP=", STRLENOF( "IP=" ) ) == 0 )
1887 ip
.bv_val
= op
->o_conn
->c_peer_name
.bv_val
+ STRLENOF( "IP=" );
1888 ip
.bv_len
= op
->o_conn
->c_peer_name
.bv_len
- STRLENOF( "IP=" );
1890 ptr
= ber_bvchr( &ip
, ':' );
1892 ip
.bv_len
= ptr
- ip
.bv_val
;
1896 if ( !BER_BVISNULL( &op
->o_conn
->c_peer_domain
) &&
1897 !bvmatch( &op
->o_conn
->c_peer_domain
, &bv_unknown
) )
1899 name
= op
->o_conn
->c_peer_domain
;
1902 if ( !BER_BVISNULL( &op
->o_dn
) && !BER_BVISEMPTY( &op
->o_dn
) ) {
1906 return slap_ctrl_session_tracking_add( op
, rs
, &ip
, &name
, &id
, ctrl
);