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 parseProxyAuthz;
24 static SLAP_CTRL_PARSE_FN parseManageDSAit;
25 static SLAP_CTRL_PARSE_FN parseNoOp;
26 static SLAP_CTRL_PARSE_FN parsePagedResults;
27 static SLAP_CTRL_PARSE_FN parseValuesReturnFilter;
28 static SLAP_CTRL_PARSE_FN parsePermissiveModify;
29 static SLAP_CTRL_PARSE_FN parseDomainScope;
31 #ifdef LDAP_CONTROL_SUBENTRIES
32 static SLAP_CTRL_PARSE_FN parseSubentries;
35 static SLAP_CTRL_PARSE_FN parseLdupSync;
38 #undef sc_mask /* avoid conflict with Irix 6.5 <sys/signal.h> */
44 /* Operations supported by control */
47 /* Extended operations supported by control */
48 char **sc_extendedops;
50 /* Control parsing callback */
51 SLAP_CTRL_PARSE_FN *sc_parse;
53 LDAP_SLIST_ENTRY(slap_control) sc_next;
56 static LDAP_SLIST_HEAD(ControlsList, slap_control) controls_list
57 = LDAP_SLIST_HEAD_INITIALIZER(&controls_list);
60 * all known request control OIDs should be added to this list
62 char **slap_known_controls = NULL;
64 static char *proxy_authz_extops[] = {
65 LDAP_EXOP_MODIFY_PASSWD,
70 static struct slap_control control_defs[] = {
71 { LDAP_CONTROL_ASSERT,
72 SLAP_CTRL_ACCESS, NULL,
73 parseAssert, LDAP_SLIST_ENTRY_INITIALIZER(next) },
74 { LDAP_CONTROL_VALUESRETURNFILTER,
75 SLAP_CTRL_SEARCH, NULL,
76 parseValuesReturnFilter, LDAP_SLIST_ENTRY_INITIALIZER(next) },
77 #ifdef LDAP_CONTROL_PAGEDRESULTS
78 { LDAP_CONTROL_PAGEDRESULTS,
79 SLAP_CTRL_SEARCH, NULL,
80 parsePagedResults, LDAP_SLIST_ENTRY_INITIALIZER(next) },
82 #ifdef LDAP_CONTROL_X_DOMAIN_SCOPE
83 { LDAP_CONTROL_X_DOMAIN_SCOPE,
84 SLAP_CTRL_FRONTEND|SLAP_CTRL_SEARCH, NULL,
85 parseDomainScope, LDAP_SLIST_ENTRY_INITIALIZER(next) },
87 #ifdef LDAP_CONTROL_X_PERMISSIVE_MODIFY
88 { LDAP_CONTROL_X_PERMISSIVE_MODIFY,
89 SLAP_CTRL_MODIFY, NULL,
90 parsePermissiveModify, LDAP_SLIST_ENTRY_INITIALIZER(next) },
92 #ifdef LDAP_CONTROL_SUBENTRIES
93 { LDAP_CONTROL_SUBENTRIES,
94 SLAP_CTRL_SEARCH, NULL,
95 parseSubentries, LDAP_SLIST_ENTRY_INITIALIZER(next) },
98 SLAP_CTRL_ACCESS, NULL,
99 parseNoOp, LDAP_SLIST_ENTRY_INITIALIZER(next) },
102 SLAP_CTRL_HIDE|SLAP_CTRL_SEARCH, NULL,
103 parseLdupSync, LDAP_SLIST_ENTRY_INITIALIZER(next) },
105 { LDAP_CONTROL_MANAGEDSAIT,
106 SLAP_CTRL_ACCESS, NULL,
107 parseManageDSAit, LDAP_SLIST_ENTRY_INITIALIZER(next) },
108 { LDAP_CONTROL_PROXY_AUTHZ,
109 SLAP_CTRL_FRONTEND|SLAP_CTRL_ACCESS, proxy_authz_extops,
110 parseProxyAuthz, LDAP_SLIST_ENTRY_INITIALIZER(next) },
111 { NULL, 0, NULL, 0, LDAP_SLIST_ENTRY_INITIALIZER(next) }
115 * Register a supported control.
117 * This can be called by an OpenLDAP plugin or, indirectly, by a
118 * SLAPI plugin calling slapi_register_supported_control().
121 register_supported_control(const char *controloid,
122 slap_mask_t controlmask,
124 SLAP_CTRL_PARSE_FN *controlparsefn)
126 struct slap_control *sc;
129 if ( controloid == NULL ) {
130 return LDAP_PARAM_ERROR;
133 sc = (struct slap_control *)SLAP_MALLOC( sizeof( *sc ) );
135 return LDAP_NO_MEMORY;
137 sc->sc_oid = ch_strdup( controloid );
138 sc->sc_mask = controlmask;
139 if ( controlexops != NULL ) {
140 sc->sc_extendedops = ldap_charray_dup( controlexops );
141 if ( sc->sc_extendedops == NULL ) {
143 return LDAP_NO_MEMORY;
146 sc->sc_extendedops = NULL;
148 sc->sc_parse = controlparsefn;
150 /* Update slap_known_controls, too. */
151 if ( slap_known_controls == NULL ) {
152 slap_known_controls = (char **)SLAP_MALLOC( 2 * sizeof(char *) );
153 if ( slap_known_controls == NULL ) {
154 if ( sc->sc_extendedops != NULL ) ldap_charray_free( sc->sc_extendedops );
156 return LDAP_NO_MEMORY;
158 slap_known_controls[0] = ch_strdup( sc->sc_oid );
159 slap_known_controls[1] = NULL;
161 for ( i = 0; slap_known_controls[i] != NULL; i++ )
163 slap_known_controls = (char **)SLAP_REALLOC( slap_known_controls, (i + 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[i++] = ch_strdup( sc->sc_oid );
170 slap_known_controls[i] = NULL;
173 LDAP_SLIST_NEXT( sc, sc_next ) = NULL;
174 LDAP_SLIST_INSERT_HEAD( &controls_list, sc, sc_next );
180 * One-time initialization of internal controls.
183 slap_controls_init( void )
186 struct slap_control *sc;
190 for ( i = 0; control_defs[i].sc_oid != NULL; i++ ) {
191 rc = register_supported_control( control_defs[i].sc_oid,
192 control_defs[i].sc_mask, control_defs[i].sc_extendedops,
193 control_defs[i].sc_parse );
194 if ( rc != LDAP_SUCCESS )
202 * Free memory associated with list of supported controls.
205 controls_destroy( void )
207 struct slap_control *sc;
209 while ( !LDAP_SLIST_EMPTY(&controls_list) ) {
210 sc = LDAP_SLIST_FIRST(&controls_list);
211 LDAP_SLIST_REMOVE_HEAD(&controls_list, sc_next);
213 ch_free( sc->sc_oid );
214 if ( sc->sc_extendedops != NULL ) {
215 ldap_charray_free( sc->sc_extendedops );
219 ldap_charray_free( slap_known_controls );
223 * Format the supportedControl attribute of the root DSE,
224 * detailing which controls are supported by the directory
228 controls_root_dse_info( Entry *e )
230 AttributeDescription *ad_supportedControl
231 = slap_schema.si_ad_supportedControl;
232 struct berval vals[2];
233 struct slap_control *sc;
235 vals[1].bv_val = NULL;
238 LDAP_SLIST_FOREACH( sc, &controls_list, sc_next ) {
239 if( sc->sc_mask & SLAP_CTRL_HIDE ) continue;
241 vals[0].bv_val = sc->sc_oid;
242 vals[0].bv_len = strlen( sc->sc_oid );
244 if ( attr_merge( e, ad_supportedControl, vals, NULL ) ) {
253 * Return a list of OIDs and operation masks for supported
254 * controls. Used by SLAPI.
257 get_supported_controls(char ***ctrloidsp,
258 slap_mask_t **ctrlmasks)
264 struct slap_control *sc;
268 LDAP_SLIST_FOREACH( sc, &controls_list, sc_next ) {
278 oids = (char **)SLAP_MALLOC( (n + 1) * sizeof(char *) );
279 if ( oids == NULL ) {
280 return LDAP_NO_MEMORY;
282 masks = (slap_mask_t *)SLAP_MALLOC( (n + 1) * sizeof(slap_mask_t) );
283 if ( masks == NULL ) {
285 return LDAP_NO_MEMORY;
290 LDAP_SLIST_FOREACH( sc, &controls_list, sc_next ) {
291 oids[n] = ch_strdup( sc->sc_oid );
292 masks[n] = sc->sc_mask;
305 * Find a control given its OID.
307 static struct slap_control *
308 find_ctrl( const char *oid )
310 struct slap_control *sc;
312 LDAP_SLIST_FOREACH( sc, &controls_list, sc_next ) {
313 if ( strcmp( oid, sc->sc_oid ) == 0 ) {
321 void slap_free_ctrls(
328 for (i=0; ctrls[i]; i++) {
329 op->o_tmpfree(ctrls[i], op->o_tmpmemctx );
331 op->o_tmpfree( ctrls, op->o_tmpmemctx );
343 BerElement *ber = op->o_ber;
344 struct slap_control *sc;
347 len = ber_pvt_ber_remaining(ber);
351 rs->sr_err = LDAP_SUCCESS;
355 if(( tag = ber_peek_tag( ber, &len )) != LDAP_TAG_CONTROLS ) {
356 if( tag == LBER_ERROR ) {
357 rs->sr_err = SLAPD_DISCONNECT;
358 rs->sr_text = "unexpected data in PDU";
365 LDAP_LOG( OPERATION, ENTRY,
366 "get_ctrls: conn %lu\n", op->o_connid, 0, 0 );
368 Debug( LDAP_DEBUG_TRACE,
369 "=> get_ctrls\n", 0, 0, 0 );
372 if( op->o_protocol < LDAP_VERSION3 ) {
373 rs->sr_err = SLAPD_DISCONNECT;
374 rs->sr_text = "controls require LDAPv3";
378 /* one for first control, one for termination */
379 op->o_ctrls = op->o_tmpalloc( 2 * sizeof(LDAPControl *), op->o_tmpmemctx );
382 if( op->ctrls == NULL ) {
383 rs->sr_err = LDAP_NO_MEMORY;
384 rs->sr_text = "no memory";
389 op->o_ctrls[nctrls] = NULL;
391 /* step through each element */
392 for( tag = ber_first_element( ber, &len, &opaque );
394 tag = ber_next_element( ber, &len, opaque ) )
397 LDAPControl **tctrls;
399 c = op->o_tmpalloc( sizeof(LDAPControl), op->o_tmpmemctx );
400 memset(c, 0, sizeof(LDAPControl));
402 /* allocate pointer space for current controls (nctrls)
403 * + this control + extra NULL
405 tctrls = op->o_tmprealloc( op->o_ctrls,
406 (nctrls+2) * sizeof(LDAPControl *), op->o_tmpmemctx );
409 if( tctrls == NULL ) {
411 ldap_controls_free(op->o_ctrls);
414 rs->sr_err = LDAP_NO_MEMORY;
415 rs->sr_text = "no memory";
419 op->o_ctrls = tctrls;
421 op->o_ctrls[nctrls++] = c;
422 op->o_ctrls[nctrls] = NULL;
424 tag = ber_scanf( ber, "{m" /*}*/, &bv );
425 c->ldctl_oid = bv.bv_val;
427 if( tag == LBER_ERROR ) {
429 LDAP_LOG( OPERATION, INFO, "get_ctrls: conn %lu get OID failed.\n",
430 op->o_connid, 0, 0 );
432 Debug( LDAP_DEBUG_TRACE, "=> get_ctrls: get oid failed.\n",
436 slap_free_ctrls( op, op->o_ctrls );
438 rs->sr_err = SLAPD_DISCONNECT;
439 rs->sr_text = "decoding controls error";
442 } else if( c->ldctl_oid == NULL ) {
444 LDAP_LOG( OPERATION, INFO,
445 "get_ctrls: conn %lu got emtpy OID.\n",
446 op->o_connid, 0, 0 );
448 Debug( LDAP_DEBUG_TRACE,
449 "get_ctrls: conn %lu got emtpy OID.\n",
450 op->o_connid, 0, 0 );
453 slap_free_ctrls( op, op->o_ctrls );
455 rs->sr_err = LDAP_PROTOCOL_ERROR;
456 rs->sr_text = "OID field is empty";
460 tag = ber_peek_tag( ber, &len );
462 if( tag == LBER_BOOLEAN ) {
464 tag = ber_scanf( ber, "b", &crit );
466 if( tag == LBER_ERROR ) {
468 LDAP_LOG( OPERATION, INFO,
469 "get_ctrls: conn %lu get crit failed.\n",
470 op->o_connid, 0, 0 );
472 Debug( LDAP_DEBUG_TRACE, "=> get_ctrls: get crit failed.\n",
475 slap_free_ctrls( op, op->o_ctrls );
477 rs->sr_err = SLAPD_DISCONNECT;
478 rs->sr_text = "decoding controls error";
482 c->ldctl_iscritical = (crit != 0);
483 tag = ber_peek_tag( ber, &len );
486 if( tag == LBER_OCTETSTRING ) {
487 tag = ber_scanf( ber, "m", &c->ldctl_value );
489 if( tag == LBER_ERROR ) {
491 LDAP_LOG( OPERATION, INFO, "get_ctrls: conn %lu: "
492 "%s (%scritical): get value failed.\n",
493 op->o_connid, c->ldctl_oid,
494 c->ldctl_iscritical ? "" : "non" );
496 Debug( LDAP_DEBUG_TRACE, "=> get_ctrls: conn %lu: "
497 "%s (%scritical): get value failed.\n",
498 op->o_connid, c->ldctl_oid,
499 c->ldctl_iscritical ? "" : "non" );
501 slap_free_ctrls( op, op->o_ctrls );
503 rs->sr_err = SLAPD_DISCONNECT;
504 rs->sr_text = "decoding controls error";
510 LDAP_LOG( OPERATION, INFO,
511 "get_ctrls: conn %lu oid=\"%s\" (%scritical)\n",
512 op->o_connid, c->ldctl_oid, c->ldctl_iscritical ? "" : "non" );
514 Debug( LDAP_DEBUG_TRACE,
515 "=> get_ctrls: oid=\"%s\" (%scritical)\n",
516 c->ldctl_oid, c->ldctl_iscritical ? "" : "non", 0 );
519 sc = find_ctrl( c->ldctl_oid );
521 /* recognized control */
523 switch( op->o_tag ) {
525 tagmask = SLAP_CTRL_ADD;
528 tagmask = SLAP_CTRL_BIND;
530 case LDAP_REQ_COMPARE:
531 tagmask = SLAP_CTRL_COMPARE;
533 case LDAP_REQ_DELETE:
534 tagmask = SLAP_CTRL_DELETE;
536 case LDAP_REQ_MODIFY:
537 tagmask = SLAP_CTRL_MODIFY;
539 case LDAP_REQ_RENAME:
540 tagmask = SLAP_CTRL_RENAME;
542 case LDAP_REQ_SEARCH:
543 tagmask = SLAP_CTRL_SEARCH;
545 case LDAP_REQ_UNBIND:
546 tagmask = SLAP_CTRL_UNBIND;
548 case LDAP_REQ_ABANDON:
549 tagmask = SLAP_CTRL_ABANDON;
551 case LDAP_REQ_EXTENDED:
553 assert( op->ore_reqoid.bv_val != NULL );
554 if( sc->sc_extendedops != NULL ) {
556 for( i=0; sc->sc_extendedops[i] != NULL; i++ ) {
557 if( strcmp( op->ore_reqoid.bv_val, sc->sc_extendedops[i] )
567 rs->sr_err = LDAP_OTHER;
568 rs->sr_text = "controls internal error";
572 if (( sc->sc_mask & tagmask ) == tagmask ) {
573 /* available extension */
575 if( !sc->sc_parse ) {
576 rs->sr_err = LDAP_OTHER;
577 rs->sr_text = "not yet implemented";
581 rs->sr_err = sc->sc_parse( op, rs, c );
583 if( rs->sr_err != LDAP_SUCCESS ) goto return_results;
585 if ( sc->sc_mask & SLAP_CTRL_FRONTEND ) {
586 /* kludge to disable backend_control() check */
587 c->ldctl_iscritical = 0;
589 } else if ( tagmask == SLAP_CTRL_SEARCH &&
590 sc->sc_mask & SLAP_CTRL_FRONTEND_SEARCH )
592 /* kludge to disable backend_control() check */
593 c->ldctl_iscritical = 0;
596 } else if( c->ldctl_iscritical ) {
597 /* unavailable CRITICAL control */
598 rs->sr_err = LDAP_UNAVAILABLE_CRITICAL_EXTENSION;
599 rs->sr_text = "critical extension is unavailable";
603 } else if( c->ldctl_iscritical ) {
604 /* unrecognized CRITICAL control */
605 rs->sr_err = LDAP_UNAVAILABLE_CRITICAL_EXTENSION;
606 rs->sr_text = "critical extension is not recognized";
613 LDAP_LOG( OPERATION, RESULTS,
614 "get_ctrls: n=%d rc=%d err=\"%s\"\n",
615 nctrls, rs->sr_err, rs->sr_text ? rs->sr_text : "" );
617 Debug( LDAP_DEBUG_TRACE,
618 "<= get_ctrls: n=%d rc=%d err=\"%s\"\n",
619 nctrls, rs->sr_err, rs->sr_text ? rs->sr_text : "");
622 if( sendres && rs->sr_err != LDAP_SUCCESS ) {
623 if( rs->sr_err == SLAPD_DISCONNECT ) {
624 rs->sr_err = LDAP_PROTOCOL_ERROR;
625 send_ldap_disconnect( op, rs );
626 rs->sr_err = SLAPD_DISCONNECT;
628 send_ldap_result( op, rs );
635 static int parseManageDSAit (
640 if ( op->o_managedsait != SLAP_NO_CONTROL ) {
641 rs->sr_text = "manageDSAit control specified multiple times";
642 return LDAP_PROTOCOL_ERROR;
645 if ( ctrl->ldctl_value.bv_len ) {
646 rs->sr_text = "manageDSAit control value not empty";
647 return LDAP_PROTOCOL_ERROR;
650 op->o_managedsait = ctrl->ldctl_iscritical
651 ? SLAP_CRITICAL_CONTROL
652 : SLAP_NONCRITICAL_CONTROL;
657 static int parseProxyAuthz (
663 struct berval dn = { 0, NULL };
665 if ( op->o_proxy_authz != SLAP_NO_CONTROL ) {
666 rs->sr_text = "proxy authorization control specified multiple times";
667 return LDAP_PROTOCOL_ERROR;
670 op->o_proxy_authz = ctrl->ldctl_iscritical
671 ? SLAP_CRITICAL_CONTROL
672 : SLAP_NONCRITICAL_CONTROL;
675 LDAP_LOG( OPERATION, ARGS,
676 "parseProxyAuthz: conn %lu authzid=\"%s\"\n",
678 ctrl->ldctl_value.bv_len ? ctrl->ldctl_value.bv_val : "anonymous",
681 Debug( LDAP_DEBUG_ARGS,
682 "parseProxyAuthz: conn %lu authzid=\"%s\"\n",
684 ctrl->ldctl_value.bv_len ? ctrl->ldctl_value.bv_val : "anonymous",
688 if( ctrl->ldctl_value.bv_len == 0 ) {
690 LDAP_LOG( OPERATION, RESULTS,
691 "parseProxyAuthz: conn=%lu anonymous\n",
692 op->o_connid, 0, 0 );
694 Debug( LDAP_DEBUG_TRACE,
695 "parseProxyAuthz: conn=%lu anonymous\n",
696 op->o_connid, 0, 0 );
700 free( op->o_dn.bv_val );
702 op->o_dn.bv_val = ch_strdup( "" );
704 free( op->o_ndn.bv_val );
705 op->o_ndn.bv_len = 0;
706 op->o_ndn.bv_val = ch_strdup( "" );
711 rc = slap_sasl_getdn( op->o_conn, op,
712 ctrl->ldctl_value.bv_val, ctrl->ldctl_value.bv_len,
713 NULL, &dn, SLAP_GETDN_AUTHZID );
715 if( rc != LDAP_SUCCESS || !dn.bv_len ) {
717 ch_free( dn.bv_val );
719 rs->sr_text = "authzId mapping failed";
720 return LDAP_PROXY_AUTHZ_FAILURE;
724 LDAP_LOG( OPERATION, RESULTS,
725 "parseProxyAuthz: conn=%lu \"%s\"\n",
727 dn.bv_len ? dn.bv_val : "(NULL)", 0 );
729 Debug( LDAP_DEBUG_TRACE,
730 "parseProxyAuthz: conn=%lu \"%s\"\n",
732 dn.bv_len ? dn.bv_val : "(NULL)", 0 );
735 rc = slap_sasl_authorized( op, &op->o_ndn, &dn );
738 ch_free( dn.bv_val );
739 rs->sr_text = "not authorized to assume identity";
740 return LDAP_PROXY_AUTHZ_FAILURE;
743 ch_free( op->o_dn.bv_val );
744 ch_free( op->o_ndn.bv_val );
746 op->o_dn.bv_val = NULL;
750 * NOTE: since slap_sasl_getdn() returns a normalized dn,
751 * from now on op->o_dn is normalized
753 ber_dupbv( &op->o_dn, &dn );
758 static int parseNoOp (
763 if ( op->o_noop != SLAP_NO_CONTROL ) {
764 rs->sr_text = "noop control specified multiple times";
765 return LDAP_PROTOCOL_ERROR;
768 if ( ctrl->ldctl_value.bv_len ) {
769 rs->sr_text = "noop control value not empty";
770 return LDAP_PROTOCOL_ERROR;
773 op->o_noop = ctrl->ldctl_iscritical
774 ? SLAP_CRITICAL_CONTROL
775 : SLAP_NONCRITICAL_CONTROL;
780 #ifdef LDAP_CONTROL_PAGEDRESULTS
781 static int parsePagedResults (
789 struct berval cookie = { 0, NULL };
791 if ( op->o_pagedresults != SLAP_NO_CONTROL ) {
792 rs->sr_text = "paged results control specified multiple times";
793 return LDAP_PROTOCOL_ERROR;
796 if ( ctrl->ldctl_value.bv_len == 0 ) {
797 rs->sr_text = "paged results control value is empty (or absent)";
798 return LDAP_PROTOCOL_ERROR;
801 /* Parse the control value
802 * realSearchControlValue ::= SEQUENCE {
803 * size INTEGER (0..maxInt),
804 * -- requested page size from client
805 * -- result set size estimate from server
806 * cookie OCTET STRING
809 ber = ber_init( &ctrl->ldctl_value );
811 rs->sr_text = "internal error";
815 tag = ber_scanf( ber, "{im}", &size, &cookie );
816 (void) ber_free( ber, 1 );
818 if( tag == LBER_ERROR ) {
819 rs->sr_text = "paged results control could not be decoded";
820 return LDAP_PROTOCOL_ERROR;
824 rs->sr_text = "paged results control size invalid";
825 return LDAP_PROTOCOL_ERROR;
828 if( cookie.bv_len ) {
829 PagedResultsCookie reqcookie;
830 if( cookie.bv_len != sizeof( reqcookie ) ) {
832 rs->sr_text = "paged results cookie is invalid";
833 return LDAP_PROTOCOL_ERROR;
836 AC_MEMCPY( &reqcookie, cookie.bv_val, sizeof( reqcookie ));
838 if( reqcookie > op->o_pagedresults_state.ps_cookie ) {
840 rs->sr_text = "paged results cookie is invalid";
841 return LDAP_PROTOCOL_ERROR;
843 } else if( reqcookie < op->o_pagedresults_state.ps_cookie ) {
844 rs->sr_text = "paged results cookie is invalid or old";
845 return LDAP_UNWILLING_TO_PERFORM;
848 /* Initial request. Initialize state. */
849 op->o_pagedresults_state.ps_cookie = 0;
850 op->o_pagedresults_state.ps_id = NOID;
853 op->o_pagedresults_size = size;
855 op->o_pagedresults = ctrl->ldctl_iscritical
856 ? SLAP_CRITICAL_CONTROL
857 : SLAP_NONCRITICAL_CONTROL;
863 static int parseAssert (
869 struct berval fstr = { 0, NULL };
870 const char *err_msg = "";
872 if ( op->o_assert != SLAP_NO_CONTROL ) {
873 rs->sr_text = "assert control specified multiple times";
874 return LDAP_PROTOCOL_ERROR;
877 if ( ctrl->ldctl_value.bv_len == 0 ) {
878 rs->sr_text = "assert control value is empty (or absent)";
879 return LDAP_PROTOCOL_ERROR;
882 ber = ber_init( &(ctrl->ldctl_value) );
884 rs->sr_text = "internal error";
888 rs->sr_err = get_filter( op, ber, &(op->o_assertion), &rs->sr_text);
890 if( rs->sr_err != LDAP_SUCCESS ) {
891 if( rs->sr_err == SLAPD_DISCONNECT ) {
892 rs->sr_err = LDAP_PROTOCOL_ERROR;
893 send_ldap_disconnect( op, rs );
894 rs->sr_err = SLAPD_DISCONNECT;
896 send_ldap_result( op, rs );
898 if( op->o_assertion != NULL) {
899 filter_free_x( op, op->o_assertion );
904 filter2bv_x( op, op->o_assertion, &fstr );
908 LDAP_LOG( OPERATION, ARGS,
909 "parseAssert: conn %ld assert: %s\n",
910 op->o_connid, fstr.bv_len ? fstr.bv_val : "empty" , 0 );
912 Debug( LDAP_DEBUG_ARGS, "parseAssert: conn %ld assert: %s\n",
913 op->o_connid, fstr.bv_len ? fstr.bv_val : "empty" , 0 );
915 op->o_tmpfree( fstr.bv_val, op->o_tmpmemctx );
918 op->o_assert = ctrl->ldctl_iscritical
919 ? SLAP_CRITICAL_CONTROL
920 : SLAP_NONCRITICAL_CONTROL;
922 rs->sr_err = LDAP_SUCCESS;
926 int parseValuesReturnFilter (
932 struct berval fstr = { 0, NULL };
933 const char *err_msg = "";
935 if ( op->o_valuesreturnfilter != SLAP_NO_CONTROL ) {
936 rs->sr_text = "valuesReturnFilter control specified multiple times";
937 return LDAP_PROTOCOL_ERROR;
940 if ( ctrl->ldctl_value.bv_len == 0 ) {
941 rs->sr_text = "valuesReturnFilter control value is empty (or absent)";
942 return LDAP_PROTOCOL_ERROR;
945 ber = ber_init( &(ctrl->ldctl_value) );
947 rs->sr_text = "internal error";
951 rs->sr_err = get_vrFilter( op, ber, &(op->o_vrFilter), &rs->sr_text);
953 if( rs->sr_err != LDAP_SUCCESS ) {
954 if( rs->sr_err == SLAPD_DISCONNECT ) {
955 rs->sr_err = LDAP_PROTOCOL_ERROR;
956 send_ldap_disconnect( op, rs );
957 rs->sr_err = SLAPD_DISCONNECT;
959 send_ldap_result( op, rs );
961 if( op->o_vrFilter != NULL) vrFilter_free( op, op->o_vrFilter );
966 vrFilter2bv( op, op->o_vrFilter, &fstr );
970 LDAP_LOG( OPERATION, ARGS,
971 "parseValuesReturnFilter: conn %d vrFilter: %s\n",
972 op->o_connid, fstr.bv_len ? fstr.bv_val : "empty" , 0 );
974 Debug( LDAP_DEBUG_ARGS, " vrFilter: %s\n",
975 fstr.bv_len ? fstr.bv_val : "empty", 0, 0 );
977 op->o_tmpfree( fstr.bv_val, op->o_tmpmemctx );
980 op->o_valuesreturnfilter = ctrl->ldctl_iscritical
981 ? SLAP_CRITICAL_CONTROL
982 : SLAP_NONCRITICAL_CONTROL;
984 rs->sr_err = LDAP_SUCCESS;
988 #ifdef LDAP_CONTROL_SUBENTRIES
989 static int parseSubentries (
994 if ( op->o_subentries != SLAP_NO_CONTROL ) {
995 rs->sr_text = "subentries control specified multiple times";
996 return LDAP_PROTOCOL_ERROR;
999 /* FIXME: should use BER library */
1000 if( ( ctrl->ldctl_value.bv_len != 3 )
1001 && ( ctrl->ldctl_value.bv_val[0] != 0x01 )
1002 && ( ctrl->ldctl_value.bv_val[1] != 0x01 ))
1004 rs->sr_text = "subentries control value encoding is bogus";
1005 return LDAP_PROTOCOL_ERROR;
1008 op->o_subentries = ctrl->ldctl_iscritical
1009 ? SLAP_CRITICAL_CONTROL
1010 : SLAP_NONCRITICAL_CONTROL;
1012 op->o_subentries_visibility = (ctrl->ldctl_value.bv_val[2] != 0x00);
1014 return LDAP_SUCCESS;
1018 #ifdef LDAP_CONTROL_X_PERMISSIVE_MODIFY
1019 static int parsePermissiveModify (
1024 if ( op->o_permissive_modify != SLAP_NO_CONTROL ) {
1025 rs->sr_text = "permissiveModify control specified multiple times";
1026 return LDAP_PROTOCOL_ERROR;
1029 if ( ctrl->ldctl_value.bv_len ) {
1030 rs->sr_text = "permissiveModify control value not empty";
1031 return LDAP_PROTOCOL_ERROR;
1034 op->o_permissive_modify = ctrl->ldctl_iscritical
1035 ? SLAP_CRITICAL_CONTROL
1036 : SLAP_NONCRITICAL_CONTROL;
1038 return LDAP_SUCCESS;
1042 #ifdef LDAP_CONTROL_X_DOMAIN_SCOPE
1043 static int parseDomainScope (
1048 if ( op->o_domain_scope != SLAP_NO_CONTROL ) {
1049 rs->sr_text = "domainScope control specified multiple times";
1050 return LDAP_PROTOCOL_ERROR;
1053 if ( ctrl->ldctl_value.bv_len ) {
1054 rs->sr_text = "domainScope control value not empty";
1055 return LDAP_PROTOCOL_ERROR;
1058 op->o_domain_scope = ctrl->ldctl_iscritical
1059 ? SLAP_CRITICAL_CONTROL
1060 : SLAP_NONCRITICAL_CONTROL;
1062 return LDAP_SUCCESS;
1067 static int parseLdupSync (
1076 struct berval cookie = { 0, NULL };
1078 if ( op->o_sync != SLAP_NO_CONTROL ) {
1079 rs->sr_text = "LDAP Sync control specified multiple times";
1080 return LDAP_PROTOCOL_ERROR;
1083 if ( ctrl->ldctl_value.bv_len == 0 ) {
1084 rs->sr_text = "LDAP Sync control value is empty (or absent)";
1085 return LDAP_PROTOCOL_ERROR;
1088 /* Parse the control value
1089 * syncRequestValue ::= SEQUENCE {
1094 * refreshAndPersist (3)
1096 * cookie syncCookie OPTIONAL
1100 ber = ber_init( &ctrl->ldctl_value );
1102 rs->sr_text = "internal error";
1106 if ( (tag = ber_scanf( ber, "{i" /*}*/, &mode )) == LBER_ERROR ) {
1107 rs->sr_text = "LDAP Sync control : mode decoding error";
1108 return LDAP_PROTOCOL_ERROR;
1112 case LDAP_SYNC_REFRESH_ONLY:
1113 mode = SLAP_SYNC_REFRESH;
1115 case LDAP_SYNC_REFRESH_AND_PERSIST:
1116 mode = SLAP_SYNC_REFRESH_AND_PERSIST;
1119 rs->sr_text = "LDAP Sync control : unknown update mode";
1120 return LDAP_PROTOCOL_ERROR;
1123 tag = ber_peek_tag( ber, &len );
1125 if ( tag == LDAP_SYNC_TAG_COOKIE ) {
1126 if (( ber_scanf( ber, /*{*/ "m}",
1127 &cookie )) == LBER_ERROR ) {
1128 rs->sr_text = "LDAP Sync control : cookie decoding error";
1129 return LDAP_PROTOCOL_ERROR;
1132 if (( ber_scanf( ber, /*{*/ "}")) == LBER_ERROR ) {
1133 rs->sr_text = "LDAP Sync control : decoding error";
1134 return LDAP_PROTOCOL_ERROR;
1137 cookie.bv_val = NULL;
1140 ber_dupbv( &op->o_sync_state, &cookie );
1142 (void) ber_free( ber, 1 );
1144 op->o_sync_mode = (char) mode;
1146 op->o_sync = ctrl->ldctl_iscritical
1147 ? SLAP_CRITICAL_CONTROL
1148 : SLAP_NONCRITICAL_CONTROL;
1150 return LDAP_SUCCESS;