3 * Copyright 1999-2003 The OpenLDAP Foundation.
6 * Redistribution and use in source and binary forms are permitted only
7 * as authorized by the OpenLDAP Public License. A copy of this
8 * license is available at http://www.OpenLDAP.org/license.html or
9 * in file LICENSE in the top-level directory of the distribution.
15 #include <ac/string.h>
16 #include <ac/socket.h>
20 #include "../../libraries/liblber/lber-int.h"
22 static SLAP_CTRL_PARSE_FN parseAssert;
23 static SLAP_CTRL_PARSE_FN parsePreRead;
24 static SLAP_CTRL_PARSE_FN parsePostRead;
25 static SLAP_CTRL_PARSE_FN parseProxyAuthz;
26 static SLAP_CTRL_PARSE_FN parseManageDSAit;
27 static SLAP_CTRL_PARSE_FN parseModifyIncrement;
28 static SLAP_CTRL_PARSE_FN parseNoOp;
29 static SLAP_CTRL_PARSE_FN parsePagedResults;
30 static SLAP_CTRL_PARSE_FN parseValuesReturnFilter;
31 static SLAP_CTRL_PARSE_FN parsePermissiveModify;
32 static SLAP_CTRL_PARSE_FN parseDomainScope;
34 #ifdef LDAP_CONTROL_SUBENTRIES
35 static SLAP_CTRL_PARSE_FN parseSubentries;
37 static SLAP_CTRL_PARSE_FN parseLDAPsync;
39 #undef sc_mask /* avoid conflict with Irix 6.5 <sys/signal.h> */
41 const struct berval slap_pre_read_bv = BER_BVC(LDAP_CONTROL_PRE_READ);
42 const struct berval slap_post_read_bv = BER_BVC(LDAP_CONTROL_POST_READ);
48 /* Operations supported by control */
51 /* Extended operations supported by control */
52 char **sc_extendedops;
54 /* Control parsing callback */
55 SLAP_CTRL_PARSE_FN *sc_parse;
57 LDAP_SLIST_ENTRY(slap_control) sc_next;
60 static LDAP_SLIST_HEAD(ControlsList, slap_control) controls_list
61 = LDAP_SLIST_HEAD_INITIALIZER(&controls_list);
64 * all known request control OIDs should be added to this list
66 char **slap_known_controls = NULL;
68 static char *proxy_authz_extops[] = {
69 LDAP_EXOP_MODIFY_PASSWD,
74 static struct slap_control control_defs[] = {
75 { LDAP_CONTROL_ASSERT,
76 SLAP_CTRL_HIDE|SLAP_CTRL_ACCESS, NULL,
77 parseAssert, LDAP_SLIST_ENTRY_INITIALIZER(next) },
78 { LDAP_CONTROL_PRE_READ,
79 SLAP_CTRL_HIDE|SLAP_CTRL_DELETE|SLAP_CTRL_MODIFY|SLAP_CTRL_RENAME, NULL,
80 parsePreRead, LDAP_SLIST_ENTRY_INITIALIZER(next) },
81 { LDAP_CONTROL_POST_READ,
82 SLAP_CTRL_HIDE|SLAP_CTRL_ADD|SLAP_CTRL_MODIFY|SLAP_CTRL_RENAME, NULL,
83 parsePostRead, LDAP_SLIST_ENTRY_INITIALIZER(next) },
84 { LDAP_CONTROL_VALUESRETURNFILTER,
85 SLAP_CTRL_SEARCH, NULL,
86 parseValuesReturnFilter, LDAP_SLIST_ENTRY_INITIALIZER(next) },
87 #ifdef LDAP_CONTROL_PAGEDRESULTS
88 { LDAP_CONTROL_PAGEDRESULTS,
89 SLAP_CTRL_SEARCH, NULL,
90 parsePagedResults, LDAP_SLIST_ENTRY_INITIALIZER(next) },
92 #ifdef LDAP_CONTROL_X_DOMAIN_SCOPE
93 { LDAP_CONTROL_X_DOMAIN_SCOPE,
94 SLAP_CTRL_FRONTEND|SLAP_CTRL_SEARCH, NULL,
95 parseDomainScope, LDAP_SLIST_ENTRY_INITIALIZER(next) },
97 #ifdef LDAP_CONTROL_X_PERMISSIVE_MODIFY
98 { LDAP_CONTROL_X_PERMISSIVE_MODIFY,
99 SLAP_CTRL_MODIFY, NULL,
100 parsePermissiveModify, LDAP_SLIST_ENTRY_INITIALIZER(next) },
102 #ifdef LDAP_CONTROL_SUBENTRIES
103 { LDAP_CONTROL_SUBENTRIES,
104 SLAP_CTRL_SEARCH, NULL,
105 parseSubentries, LDAP_SLIST_ENTRY_INITIALIZER(next) },
108 SLAP_CTRL_ACCESS, NULL,
109 parseNoOp, LDAP_SLIST_ENTRY_INITIALIZER(next) },
111 SLAP_CTRL_HIDE|SLAP_CTRL_SEARCH, NULL,
112 parseLDAPsync, LDAP_SLIST_ENTRY_INITIALIZER(next) },
113 { LDAP_CONTROL_MODIFY_INCREMENT,
114 SLAP_CTRL_HIDE|SLAP_CTRL_MODIFY, NULL,
115 parseModifyIncrement, LDAP_SLIST_ENTRY_INITIALIZER(next) },
116 { LDAP_CONTROL_MANAGEDSAIT,
117 SLAP_CTRL_ACCESS, NULL,
118 parseManageDSAit, LDAP_SLIST_ENTRY_INITIALIZER(next) },
119 { LDAP_CONTROL_PROXY_AUTHZ,
120 SLAP_CTRL_FRONTEND|SLAP_CTRL_ACCESS, proxy_authz_extops,
121 parseProxyAuthz, LDAP_SLIST_ENTRY_INITIALIZER(next) },
122 { NULL, 0, NULL, 0, LDAP_SLIST_ENTRY_INITIALIZER(next) }
126 * Register a supported control.
128 * This can be called by an OpenLDAP plugin or, indirectly, by a
129 * SLAPI plugin calling slapi_register_supported_control().
132 register_supported_control(const char *controloid,
133 slap_mask_t controlmask,
135 SLAP_CTRL_PARSE_FN *controlparsefn)
137 struct slap_control *sc;
140 if ( controloid == NULL ) {
141 return LDAP_PARAM_ERROR;
144 sc = (struct slap_control *)SLAP_MALLOC( sizeof( *sc ) );
146 return LDAP_NO_MEMORY;
148 sc->sc_oid = ch_strdup( controloid );
149 sc->sc_mask = controlmask;
150 if ( controlexops != NULL ) {
151 sc->sc_extendedops = ldap_charray_dup( controlexops );
152 if ( sc->sc_extendedops == NULL ) {
154 return LDAP_NO_MEMORY;
157 sc->sc_extendedops = NULL;
159 sc->sc_parse = controlparsefn;
161 /* Update slap_known_controls, too. */
162 if ( slap_known_controls == NULL ) {
163 slap_known_controls = (char **)SLAP_MALLOC( 2 * sizeof(char *) );
164 if ( slap_known_controls == NULL ) {
165 if ( sc->sc_extendedops != NULL ) ldap_charray_free( sc->sc_extendedops );
167 return LDAP_NO_MEMORY;
169 slap_known_controls[0] = ch_strdup( sc->sc_oid );
170 slap_known_controls[1] = NULL;
172 for ( i = 0; slap_known_controls[i] != NULL; i++ )
174 slap_known_controls = (char **)SLAP_REALLOC( slap_known_controls, (i + 2) * sizeof(char *) );
175 if ( slap_known_controls == NULL ) {
176 if ( sc->sc_extendedops != NULL ) ldap_charray_free( sc->sc_extendedops );
178 return LDAP_NO_MEMORY;
180 slap_known_controls[i++] = ch_strdup( sc->sc_oid );
181 slap_known_controls[i] = NULL;
184 LDAP_SLIST_NEXT( sc, sc_next ) = NULL;
185 LDAP_SLIST_INSERT_HEAD( &controls_list, sc, sc_next );
191 * One-time initialization of internal controls.
194 slap_controls_init( void )
197 struct slap_control *sc;
201 for ( i = 0; control_defs[i].sc_oid != NULL; i++ ) {
202 rc = register_supported_control( control_defs[i].sc_oid,
203 control_defs[i].sc_mask, control_defs[i].sc_extendedops,
204 control_defs[i].sc_parse );
205 if ( rc != LDAP_SUCCESS )
213 * Free memory associated with list of supported controls.
216 controls_destroy( void )
218 struct slap_control *sc;
220 while ( !LDAP_SLIST_EMPTY(&controls_list) ) {
221 sc = LDAP_SLIST_FIRST(&controls_list);
222 LDAP_SLIST_REMOVE_HEAD(&controls_list, sc_next);
224 ch_free( sc->sc_oid );
225 if ( sc->sc_extendedops != NULL ) {
226 ldap_charray_free( sc->sc_extendedops );
230 ldap_charray_free( slap_known_controls );
234 * Format the supportedControl attribute of the root DSE,
235 * detailing which controls are supported by the directory
239 controls_root_dse_info( Entry *e )
241 AttributeDescription *ad_supportedControl
242 = slap_schema.si_ad_supportedControl;
243 struct berval vals[2];
244 struct slap_control *sc;
246 vals[1].bv_val = NULL;
249 LDAP_SLIST_FOREACH( sc, &controls_list, sc_next ) {
250 if( sc->sc_mask & SLAP_CTRL_HIDE ) continue;
252 vals[0].bv_val = sc->sc_oid;
253 vals[0].bv_len = strlen( sc->sc_oid );
255 if ( attr_merge( e, ad_supportedControl, vals, NULL ) ) {
264 * Return a list of OIDs and operation masks for supported
265 * controls. Used by SLAPI.
268 get_supported_controls(char ***ctrloidsp,
269 slap_mask_t **ctrlmasks)
275 struct slap_control *sc;
279 LDAP_SLIST_FOREACH( sc, &controls_list, sc_next ) {
289 oids = (char **)SLAP_MALLOC( (n + 1) * sizeof(char *) );
290 if ( oids == NULL ) {
291 return LDAP_NO_MEMORY;
293 masks = (slap_mask_t *)SLAP_MALLOC( (n + 1) * sizeof(slap_mask_t) );
294 if ( masks == NULL ) {
296 return LDAP_NO_MEMORY;
301 LDAP_SLIST_FOREACH( sc, &controls_list, sc_next ) {
302 oids[n] = ch_strdup( sc->sc_oid );
303 masks[n] = sc->sc_mask;
316 * Find a control given its OID.
318 static struct slap_control *
319 find_ctrl( const char *oid )
321 struct slap_control *sc;
323 LDAP_SLIST_FOREACH( sc, &controls_list, sc_next ) {
324 if ( strcmp( oid, sc->sc_oid ) == 0 ) {
332 void slap_free_ctrls(
339 for (i=0; ctrls[i]; i++) {
340 op->o_tmpfree(ctrls[i], op->o_tmpmemctx );
342 op->o_tmpfree( ctrls, op->o_tmpmemctx );
354 BerElement *ber = op->o_ber;
355 struct slap_control *sc;
358 len = ber_pvt_ber_remaining(ber);
362 rs->sr_err = LDAP_SUCCESS;
366 if(( tag = ber_peek_tag( ber, &len )) != LDAP_TAG_CONTROLS ) {
367 if( tag == LBER_ERROR ) {
368 rs->sr_err = SLAPD_DISCONNECT;
369 rs->sr_text = "unexpected data in PDU";
376 LDAP_LOG( OPERATION, ENTRY,
377 "get_ctrls: conn %lu\n", op->o_connid, 0, 0 );
379 Debug( LDAP_DEBUG_TRACE,
380 "=> get_ctrls\n", 0, 0, 0 );
383 if( op->o_protocol < LDAP_VERSION3 ) {
384 rs->sr_err = SLAPD_DISCONNECT;
385 rs->sr_text = "controls require LDAPv3";
389 /* one for first control, one for termination */
390 op->o_ctrls = op->o_tmpalloc( 2 * sizeof(LDAPControl *), op->o_tmpmemctx );
393 if( op->ctrls == NULL ) {
394 rs->sr_err = LDAP_NO_MEMORY;
395 rs->sr_text = "no memory";
400 op->o_ctrls[nctrls] = NULL;
402 /* step through each element */
403 for( tag = ber_first_element( ber, &len, &opaque );
405 tag = ber_next_element( ber, &len, opaque ) )
408 LDAPControl **tctrls;
410 c = op->o_tmpalloc( sizeof(LDAPControl), op->o_tmpmemctx );
411 memset(c, 0, sizeof(LDAPControl));
413 /* allocate pointer space for current controls (nctrls)
414 * + this control + extra NULL
416 tctrls = op->o_tmprealloc( op->o_ctrls,
417 (nctrls+2) * sizeof(LDAPControl *), op->o_tmpmemctx );
420 if( tctrls == NULL ) {
422 ldap_controls_free(op->o_ctrls);
425 rs->sr_err = LDAP_NO_MEMORY;
426 rs->sr_text = "no memory";
430 op->o_ctrls = tctrls;
432 op->o_ctrls[nctrls++] = c;
433 op->o_ctrls[nctrls] = NULL;
435 tag = ber_scanf( ber, "{m" /*}*/, &bv );
436 c->ldctl_oid = bv.bv_val;
438 if( tag == LBER_ERROR ) {
440 LDAP_LOG( OPERATION, INFO, "get_ctrls: conn %lu get OID failed.\n",
441 op->o_connid, 0, 0 );
443 Debug( LDAP_DEBUG_TRACE, "=> get_ctrls: get oid failed.\n",
447 slap_free_ctrls( op, op->o_ctrls );
449 rs->sr_err = SLAPD_DISCONNECT;
450 rs->sr_text = "decoding controls error";
453 } else if( c->ldctl_oid == NULL ) {
455 LDAP_LOG( OPERATION, INFO,
456 "get_ctrls: conn %lu got emtpy OID.\n",
457 op->o_connid, 0, 0 );
459 Debug( LDAP_DEBUG_TRACE,
460 "get_ctrls: conn %lu got emtpy OID.\n",
461 op->o_connid, 0, 0 );
464 slap_free_ctrls( op, op->o_ctrls );
466 rs->sr_err = LDAP_PROTOCOL_ERROR;
467 rs->sr_text = "OID field is empty";
471 tag = ber_peek_tag( ber, &len );
473 if( tag == LBER_BOOLEAN ) {
475 tag = ber_scanf( ber, "b", &crit );
477 if( tag == LBER_ERROR ) {
479 LDAP_LOG( OPERATION, INFO,
480 "get_ctrls: conn %lu get crit failed.\n",
481 op->o_connid, 0, 0 );
483 Debug( LDAP_DEBUG_TRACE, "=> get_ctrls: get crit failed.\n",
486 slap_free_ctrls( op, op->o_ctrls );
488 rs->sr_err = SLAPD_DISCONNECT;
489 rs->sr_text = "decoding controls error";
493 c->ldctl_iscritical = (crit != 0);
494 tag = ber_peek_tag( ber, &len );
497 if( tag == LBER_OCTETSTRING ) {
498 tag = ber_scanf( ber, "m", &c->ldctl_value );
500 if( tag == LBER_ERROR ) {
502 LDAP_LOG( OPERATION, INFO, "get_ctrls: conn %lu: "
503 "%s (%scritical): get value failed.\n",
504 op->o_connid, c->ldctl_oid,
505 c->ldctl_iscritical ? "" : "non" );
507 Debug( LDAP_DEBUG_TRACE, "=> get_ctrls: conn %lu: "
508 "%s (%scritical): get value failed.\n",
509 op->o_connid, c->ldctl_oid,
510 c->ldctl_iscritical ? "" : "non" );
512 slap_free_ctrls( op, op->o_ctrls );
514 rs->sr_err = SLAPD_DISCONNECT;
515 rs->sr_text = "decoding controls error";
521 LDAP_LOG( OPERATION, INFO,
522 "get_ctrls: conn %lu oid=\"%s\" (%scritical)\n",
523 op->o_connid, c->ldctl_oid, c->ldctl_iscritical ? "" : "non" );
525 Debug( LDAP_DEBUG_TRACE,
526 "=> get_ctrls: oid=\"%s\" (%scritical)\n",
527 c->ldctl_oid, c->ldctl_iscritical ? "" : "non", 0 );
530 sc = find_ctrl( c->ldctl_oid );
532 /* recognized control */
534 switch( op->o_tag ) {
536 tagmask = SLAP_CTRL_ADD;
539 tagmask = SLAP_CTRL_BIND;
541 case LDAP_REQ_COMPARE:
542 tagmask = SLAP_CTRL_COMPARE;
544 case LDAP_REQ_DELETE:
545 tagmask = SLAP_CTRL_DELETE;
547 case LDAP_REQ_MODIFY:
548 tagmask = SLAP_CTRL_MODIFY;
550 case LDAP_REQ_RENAME:
551 tagmask = SLAP_CTRL_RENAME;
553 case LDAP_REQ_SEARCH:
554 tagmask = SLAP_CTRL_SEARCH;
556 case LDAP_REQ_UNBIND:
557 tagmask = SLAP_CTRL_UNBIND;
559 case LDAP_REQ_ABANDON:
560 tagmask = SLAP_CTRL_ABANDON;
562 case LDAP_REQ_EXTENDED:
564 assert( op->ore_reqoid.bv_val != NULL );
565 if( sc->sc_extendedops != NULL ) {
567 for( i=0; sc->sc_extendedops[i] != NULL; i++ ) {
568 if( strcmp( op->ore_reqoid.bv_val, sc->sc_extendedops[i] )
578 rs->sr_err = LDAP_OTHER;
579 rs->sr_text = "controls internal error";
583 if (( sc->sc_mask & tagmask ) == tagmask ) {
584 /* available extension */
586 if( !sc->sc_parse ) {
587 rs->sr_err = LDAP_OTHER;
588 rs->sr_text = "not yet implemented";
592 rs->sr_err = sc->sc_parse( op, rs, c );
594 if( rs->sr_err != LDAP_SUCCESS ) goto return_results;
596 if ( sc->sc_mask & SLAP_CTRL_FRONTEND ) {
597 /* kludge to disable backend_control() check */
598 c->ldctl_iscritical = 0;
600 } else if ( tagmask == SLAP_CTRL_SEARCH &&
601 sc->sc_mask & SLAP_CTRL_FRONTEND_SEARCH )
603 /* kludge to disable backend_control() check */
604 c->ldctl_iscritical = 0;
607 } else if( c->ldctl_iscritical ) {
608 /* unavailable CRITICAL control */
609 rs->sr_err = LDAP_UNAVAILABLE_CRITICAL_EXTENSION;
610 rs->sr_text = "critical extension is unavailable";
614 } else if( c->ldctl_iscritical ) {
615 /* unrecognized CRITICAL control */
616 rs->sr_err = LDAP_UNAVAILABLE_CRITICAL_EXTENSION;
617 rs->sr_text = "critical extension is not recognized";
624 LDAP_LOG( OPERATION, RESULTS,
625 "get_ctrls: n=%d rc=%d err=\"%s\"\n",
626 nctrls, rs->sr_err, rs->sr_text ? rs->sr_text : "" );
628 Debug( LDAP_DEBUG_TRACE,
629 "<= get_ctrls: n=%d rc=%d err=\"%s\"\n",
630 nctrls, rs->sr_err, rs->sr_text ? rs->sr_text : "");
633 if( sendres && rs->sr_err != LDAP_SUCCESS ) {
634 if( rs->sr_err == SLAPD_DISCONNECT ) {
635 rs->sr_err = LDAP_PROTOCOL_ERROR;
636 send_ldap_disconnect( op, rs );
637 rs->sr_err = SLAPD_DISCONNECT;
639 send_ldap_result( op, rs );
646 static int parseModifyIncrement (
652 if ( op->o_parseModifyIncrement != SLAP_NO_CONTROL ) {
653 rs->sr_text = "modifyIncrement control specified multiple times";
654 return LDAP_PROTOCOL_ERROR;
658 if ( ctrl->ldctl_value.bv_len ) {
659 rs->sr_text = "modifyIncrement control value not empty";
660 return LDAP_PROTOCOL_ERROR;
664 op->o_parseModifyIncrement = ctrl->ldctl_iscritical
665 ? SLAP_CRITICAL_CONTROL
666 : SLAP_NONCRITICAL_CONTROL;
672 static int parseManageDSAit (
677 if ( op->o_managedsait != SLAP_NO_CONTROL ) {
678 rs->sr_text = "manageDSAit control specified multiple times";
679 return LDAP_PROTOCOL_ERROR;
682 if ( ctrl->ldctl_value.bv_len ) {
683 rs->sr_text = "manageDSAit control value not empty";
684 return LDAP_PROTOCOL_ERROR;
687 op->o_managedsait = ctrl->ldctl_iscritical
688 ? SLAP_CRITICAL_CONTROL
689 : SLAP_NONCRITICAL_CONTROL;
694 static int parseProxyAuthz (
700 struct berval dn = { 0, NULL };
702 if ( op->o_proxy_authz != SLAP_NO_CONTROL ) {
703 rs->sr_text = "proxy authorization control specified multiple times";
704 return LDAP_PROTOCOL_ERROR;
707 op->o_proxy_authz = ctrl->ldctl_iscritical
708 ? SLAP_CRITICAL_CONTROL
709 : SLAP_NONCRITICAL_CONTROL;
712 LDAP_LOG( OPERATION, ARGS,
713 "parseProxyAuthz: conn %lu authzid=\"%s\"\n",
715 ctrl->ldctl_value.bv_len ? ctrl->ldctl_value.bv_val : "anonymous",
718 Debug( LDAP_DEBUG_ARGS,
719 "parseProxyAuthz: conn %lu authzid=\"%s\"\n",
721 ctrl->ldctl_value.bv_len ? ctrl->ldctl_value.bv_val : "anonymous",
725 if( ctrl->ldctl_value.bv_len == 0 ) {
727 LDAP_LOG( OPERATION, RESULTS,
728 "parseProxyAuthz: conn=%lu anonymous\n",
729 op->o_connid, 0, 0 );
731 Debug( LDAP_DEBUG_TRACE,
732 "parseProxyAuthz: conn=%lu anonymous\n",
733 op->o_connid, 0, 0 );
737 free( op->o_dn.bv_val );
739 op->o_dn.bv_val = ch_strdup( "" );
741 free( op->o_ndn.bv_val );
742 op->o_ndn.bv_len = 0;
743 op->o_ndn.bv_val = ch_strdup( "" );
748 rc = slap_sasl_getdn( op->o_conn, op,
749 ctrl->ldctl_value.bv_val, ctrl->ldctl_value.bv_len,
750 NULL, &dn, SLAP_GETDN_AUTHZID );
752 if( rc != LDAP_SUCCESS || !dn.bv_len ) {
754 ch_free( dn.bv_val );
756 rs->sr_text = "authzId mapping failed";
757 return LDAP_PROXY_AUTHZ_FAILURE;
761 LDAP_LOG( OPERATION, RESULTS,
762 "parseProxyAuthz: conn=%lu \"%s\"\n",
764 dn.bv_len ? dn.bv_val : "(NULL)", 0 );
766 Debug( LDAP_DEBUG_TRACE,
767 "parseProxyAuthz: conn=%lu \"%s\"\n",
769 dn.bv_len ? dn.bv_val : "(NULL)", 0 );
772 rc = slap_sasl_authorized( op, &op->o_ndn, &dn );
775 ch_free( dn.bv_val );
776 rs->sr_text = "not authorized to assume identity";
777 return LDAP_PROXY_AUTHZ_FAILURE;
780 ch_free( op->o_dn.bv_val );
781 ch_free( op->o_ndn.bv_val );
783 op->o_dn.bv_val = NULL;
787 * NOTE: since slap_sasl_getdn() returns a normalized dn,
788 * from now on op->o_dn is normalized
790 ber_dupbv( &op->o_dn, &dn );
795 static int parseNoOp (
800 if ( op->o_noop != SLAP_NO_CONTROL ) {
801 rs->sr_text = "noop control specified multiple times";
802 return LDAP_PROTOCOL_ERROR;
805 if ( ctrl->ldctl_value.bv_len ) {
806 rs->sr_text = "noop control value not empty";
807 return LDAP_PROTOCOL_ERROR;
810 op->o_noop = ctrl->ldctl_iscritical
811 ? SLAP_CRITICAL_CONTROL
812 : SLAP_NONCRITICAL_CONTROL;
817 #ifdef LDAP_CONTROL_PAGEDRESULTS
818 static int parsePagedResults (
826 struct berval cookie = { 0, NULL };
828 if ( op->o_pagedresults != SLAP_NO_CONTROL ) {
829 rs->sr_text = "paged results control specified multiple times";
830 return LDAP_PROTOCOL_ERROR;
833 if ( ctrl->ldctl_value.bv_len == 0 ) {
834 rs->sr_text = "paged results control value is empty (or absent)";
835 return LDAP_PROTOCOL_ERROR;
838 /* Parse the control value
839 * realSearchControlValue ::= SEQUENCE {
840 * size INTEGER (0..maxInt),
841 * -- requested page size from client
842 * -- result set size estimate from server
843 * cookie OCTET STRING
846 ber = ber_init( &ctrl->ldctl_value );
848 rs->sr_text = "internal error";
852 tag = ber_scanf( ber, "{im}", &size, &cookie );
853 (void) ber_free( ber, 1 );
855 if( tag == LBER_ERROR ) {
856 rs->sr_text = "paged results control could not be decoded";
857 return LDAP_PROTOCOL_ERROR;
861 rs->sr_text = "paged results control size invalid";
862 return LDAP_PROTOCOL_ERROR;
865 if( cookie.bv_len ) {
866 PagedResultsCookie reqcookie;
867 if( cookie.bv_len != sizeof( reqcookie ) ) {
869 rs->sr_text = "paged results cookie is invalid";
870 return LDAP_PROTOCOL_ERROR;
873 AC_MEMCPY( &reqcookie, cookie.bv_val, sizeof( reqcookie ));
875 if( reqcookie > op->o_pagedresults_state.ps_cookie ) {
877 rs->sr_text = "paged results cookie is invalid";
878 return LDAP_PROTOCOL_ERROR;
880 } else if( reqcookie < op->o_pagedresults_state.ps_cookie ) {
881 rs->sr_text = "paged results cookie is invalid or old";
882 return LDAP_UNWILLING_TO_PERFORM;
885 /* Initial request. Initialize state. */
886 op->o_pagedresults_state.ps_cookie = 0;
887 op->o_pagedresults_state.ps_id = NOID;
890 op->o_pagedresults_size = size;
892 op->o_pagedresults = ctrl->ldctl_iscritical
893 ? SLAP_CRITICAL_CONTROL
894 : SLAP_NONCRITICAL_CONTROL;
900 static int parseAssert (
906 struct berval fstr = { 0, NULL };
907 const char *err_msg = "";
909 if ( op->o_assert != SLAP_NO_CONTROL ) {
910 rs->sr_text = "assert control specified multiple times";
911 return LDAP_PROTOCOL_ERROR;
914 if ( ctrl->ldctl_value.bv_len == 0 ) {
915 rs->sr_text = "assert control value is empty (or absent)";
916 return LDAP_PROTOCOL_ERROR;
919 ber = ber_init( &(ctrl->ldctl_value) );
921 rs->sr_text = "assert control: internal error";
925 rs->sr_err = get_filter( op, ber, &(op->o_assertion), &rs->sr_text);
927 if( rs->sr_err != LDAP_SUCCESS ) {
928 if( rs->sr_err == SLAPD_DISCONNECT ) {
929 rs->sr_err = LDAP_PROTOCOL_ERROR;
930 send_ldap_disconnect( op, rs );
931 rs->sr_err = SLAPD_DISCONNECT;
933 send_ldap_result( op, rs );
935 if( op->o_assertion != NULL ) {
936 filter_free_x( op, op->o_assertion );
942 filter2bv_x( op, op->o_assertion, &fstr );
945 LDAP_LOG( OPERATION, ARGS,
946 "parseAssert: conn %ld assert: %s\n",
947 op->o_connid, fstr.bv_len ? fstr.bv_val : "empty" , 0 );
949 Debug( LDAP_DEBUG_ARGS, "parseAssert: conn %ld assert: %s\n",
950 op->o_connid, fstr.bv_len ? fstr.bv_val : "empty" , 0 );
952 op->o_tmpfree( fstr.bv_val, op->o_tmpmemctx );
955 op->o_assert = ctrl->ldctl_iscritical
956 ? SLAP_CRITICAL_CONTROL
957 : SLAP_NONCRITICAL_CONTROL;
959 rs->sr_err = LDAP_SUCCESS;
963 static int parsePreRead (
968 ber_len_t siz, off, i;
969 AttributeName *an = NULL;
972 if ( op->o_preread != SLAP_NO_CONTROL ) {
973 rs->sr_text = "preread control specified multiple times";
974 return LDAP_PROTOCOL_ERROR;
977 if ( ctrl->ldctl_value.bv_len == 0 ) {
978 rs->sr_text = "preread control value is empty (or absent)";
979 return LDAP_PROTOCOL_ERROR;
982 ber = ber_init( &(ctrl->ldctl_value) );
984 rs->sr_text = "preread control: internal error";
988 siz = sizeof( AttributeName );
989 off = offsetof( AttributeName, an_name );
990 if ( ber_scanf( ber, "{M}", &an, &siz, off ) == LBER_ERROR ) {
991 rs->sr_text = "preread control: decoding error";
992 return LDAP_PROTOCOL_ERROR;
995 for( i=0; i<siz; i++ ) {
997 an[i].an_desc = NULL;
999 slap_bv2ad( &an[i].an_name, &an[i].an_desc, &dummy );
1002 op->o_preread = ctrl->ldctl_iscritical
1003 ? SLAP_CRITICAL_CONTROL
1004 : SLAP_NONCRITICAL_CONTROL;
1006 op->o_preread_attrs = an;
1008 rs->sr_err = LDAP_SUCCESS;
1009 return LDAP_SUCCESS;
1012 static int parsePostRead (
1017 ber_len_t siz, off, i;
1018 AttributeName *an = NULL;
1021 if ( op->o_postread != SLAP_NO_CONTROL ) {
1022 rs->sr_text = "postread control specified multiple times";
1023 return LDAP_PROTOCOL_ERROR;
1026 if ( ctrl->ldctl_value.bv_len == 0 ) {
1027 rs->sr_text = "postread control value is empty (or absent)";
1028 return LDAP_PROTOCOL_ERROR;
1031 ber = ber_init( &(ctrl->ldctl_value) );
1033 rs->sr_text = "postread control: internal error";
1037 siz = sizeof( AttributeName );
1038 off = offsetof( AttributeName, an_name );
1039 if ( ber_scanf( ber, "{M}", &an, &siz, off ) == LBER_ERROR ) {
1040 rs->sr_text = "postread control: decoding error";
1041 return LDAP_PROTOCOL_ERROR;
1044 for( i=0; i<siz; i++ ) {
1046 an[i].an_desc = NULL;
1048 slap_bv2ad( &an[i].an_name, &an[i].an_desc, &dummy );
1051 op->o_postread = ctrl->ldctl_iscritical
1052 ? SLAP_CRITICAL_CONTROL
1053 : SLAP_NONCRITICAL_CONTROL;
1055 op->o_postread_attrs = an;
1057 rs->sr_err = LDAP_SUCCESS;
1058 return LDAP_SUCCESS;
1061 int parseValuesReturnFilter (
1067 struct berval fstr = { 0, NULL };
1068 const char *err_msg = "";
1070 if ( op->o_valuesreturnfilter != SLAP_NO_CONTROL ) {
1071 rs->sr_text = "valuesReturnFilter control specified multiple times";
1072 return LDAP_PROTOCOL_ERROR;
1075 if ( ctrl->ldctl_value.bv_len == 0 ) {
1076 rs->sr_text = "valuesReturnFilter control value is empty (or absent)";
1077 return LDAP_PROTOCOL_ERROR;
1080 ber = ber_init( &(ctrl->ldctl_value) );
1082 rs->sr_text = "internal error";
1086 rs->sr_err = get_vrFilter( op, ber, &(op->o_vrFilter), &rs->sr_text);
1088 if( rs->sr_err != LDAP_SUCCESS ) {
1089 if( rs->sr_err == SLAPD_DISCONNECT ) {
1090 rs->sr_err = LDAP_PROTOCOL_ERROR;
1091 send_ldap_disconnect( op, rs );
1092 rs->sr_err = SLAPD_DISCONNECT;
1094 send_ldap_result( op, rs );
1096 if( op->o_vrFilter != NULL) vrFilter_free( op, op->o_vrFilter );
1100 vrFilter2bv( op, op->o_vrFilter, &fstr );
1104 LDAP_LOG( OPERATION, ARGS,
1105 "parseValuesReturnFilter: conn %d vrFilter: %s\n",
1106 op->o_connid, fstr.bv_len ? fstr.bv_val : "empty" , 0 );
1108 Debug( LDAP_DEBUG_ARGS, " vrFilter: %s\n",
1109 fstr.bv_len ? fstr.bv_val : "empty", 0, 0 );
1111 op->o_tmpfree( fstr.bv_val, op->o_tmpmemctx );
1114 op->o_valuesreturnfilter = ctrl->ldctl_iscritical
1115 ? SLAP_CRITICAL_CONTROL
1116 : SLAP_NONCRITICAL_CONTROL;
1118 rs->sr_err = LDAP_SUCCESS;
1119 return LDAP_SUCCESS;
1122 #ifdef LDAP_CONTROL_SUBENTRIES
1123 static int parseSubentries (
1128 if ( op->o_subentries != SLAP_NO_CONTROL ) {
1129 rs->sr_text = "subentries control specified multiple times";
1130 return LDAP_PROTOCOL_ERROR;
1133 /* FIXME: should use BER library */
1134 if( ( ctrl->ldctl_value.bv_len != 3 )
1135 && ( ctrl->ldctl_value.bv_val[0] != 0x01 )
1136 && ( ctrl->ldctl_value.bv_val[1] != 0x01 ))
1138 rs->sr_text = "subentries control value encoding is bogus";
1139 return LDAP_PROTOCOL_ERROR;
1142 op->o_subentries = ctrl->ldctl_iscritical
1143 ? SLAP_CRITICAL_CONTROL
1144 : SLAP_NONCRITICAL_CONTROL;
1146 op->o_subentries_visibility = (ctrl->ldctl_value.bv_val[2] != 0x00);
1148 return LDAP_SUCCESS;
1152 #ifdef LDAP_CONTROL_X_PERMISSIVE_MODIFY
1153 static int parsePermissiveModify (
1158 if ( op->o_permissive_modify != SLAP_NO_CONTROL ) {
1159 rs->sr_text = "permissiveModify control specified multiple times";
1160 return LDAP_PROTOCOL_ERROR;
1163 if ( ctrl->ldctl_value.bv_len ) {
1164 rs->sr_text = "permissiveModify control value not empty";
1165 return LDAP_PROTOCOL_ERROR;
1168 op->o_permissive_modify = ctrl->ldctl_iscritical
1169 ? SLAP_CRITICAL_CONTROL
1170 : SLAP_NONCRITICAL_CONTROL;
1172 return LDAP_SUCCESS;
1176 #ifdef LDAP_CONTROL_X_DOMAIN_SCOPE
1177 static int parseDomainScope (
1182 if ( op->o_domain_scope != SLAP_NO_CONTROL ) {
1183 rs->sr_text = "domainScope control specified multiple times";
1184 return LDAP_PROTOCOL_ERROR;
1187 if ( ctrl->ldctl_value.bv_len ) {
1188 rs->sr_text = "domainScope control value not empty";
1189 return LDAP_PROTOCOL_ERROR;
1192 op->o_domain_scope = ctrl->ldctl_iscritical
1193 ? SLAP_CRITICAL_CONTROL
1194 : SLAP_NONCRITICAL_CONTROL;
1196 return LDAP_SUCCESS;
1200 static int parseLDAPsync (
1209 struct slap_session_entry *se;
1211 if ( op->o_sync != SLAP_NO_CONTROL ) {
1212 rs->sr_text = "LDAP Sync control specified multiple times";
1213 return LDAP_PROTOCOL_ERROR;
1216 if ( ctrl->ldctl_value.bv_len == 0 ) {
1217 rs->sr_text = "LDAP Sync control value is empty (or absent)";
1218 return LDAP_PROTOCOL_ERROR;
1221 /* Parse the control value
1222 * syncRequestValue ::= SEQUENCE {
1227 * refreshAndPersist (3)
1229 * cookie syncCookie OPTIONAL
1233 ber = ber_init( &ctrl->ldctl_value );
1235 rs->sr_text = "internal error";
1239 if ( (tag = ber_scanf( ber, "{i" /*}*/, &mode )) == LBER_ERROR ) {
1240 rs->sr_text = "LDAP Sync control : mode decoding error";
1241 return LDAP_PROTOCOL_ERROR;
1245 case LDAP_SYNC_REFRESH_ONLY:
1246 mode = SLAP_SYNC_REFRESH;
1248 case LDAP_SYNC_REFRESH_AND_PERSIST:
1249 mode = SLAP_SYNC_REFRESH_AND_PERSIST;
1252 rs->sr_text = "LDAP Sync control : unknown update mode";
1253 return LDAP_PROTOCOL_ERROR;
1256 tag = ber_peek_tag( ber, &len );
1258 if ( tag == LDAP_TAG_SYNC_COOKIE ) {
1259 struct berval tmp_bv;
1260 if (( ber_scanf( ber, /*{*/ "o", &tmp_bv )) == LBER_ERROR ) {
1261 rs->sr_text = "LDAP Sync control : cookie decoding error";
1262 return LDAP_PROTOCOL_ERROR;
1264 ber_bvarray_add( &op->o_sync_state.octet_str, &tmp_bv );
1265 slap_parse_sync_cookie( &op->o_sync_state );
1267 if ( tag == LDAP_TAG_RELOAD_HINT ) {
1268 if (( ber_scanf( ber, /*{*/ "b", &op->o_sync_rhint )) == LBER_ERROR ) {
1269 rs->sr_text = "LDAP Sync control : rhint decoding error";
1270 return LDAP_PROTOCOL_ERROR;
1273 if (( ber_scanf( ber, /*{*/ "}")) == LBER_ERROR ) {
1274 rs->sr_text = "LDAP Sync control : decoding error";
1275 return LDAP_PROTOCOL_ERROR;
1278 (void) ber_free( ber, 1 );
1280 op->o_sync_mode = (char) mode;
1282 op->o_sync = ctrl->ldctl_iscritical
1283 ? SLAP_CRITICAL_CONTROL
1284 : SLAP_NONCRITICAL_CONTROL;
1286 return LDAP_SUCCESS;