3 * Copyright 1999-2002 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 #define SLAP_CTRL_ABANDON 0x0001
23 #define SLAP_CTRL_ADD 0x2002
24 #define SLAP_CTRL_BIND 0x0004
25 #define SLAP_CTRL_COMPARE 0x1008
26 #define SLAP_CTRL_DELETE 0x2010
27 #define SLAP_CTRL_MODIFY 0x2020
28 #define SLAP_CTRL_RENAME 0x2040
29 #define SLAP_CTRL_SEARCH 0x1080
30 #define SLAP_CTRL_UNBIND 0x0100
32 #define SLAP_CTRL_INTROGATE (SLAP_CTRL_COMPARE|SLAP_CTRL_SEARCH)
33 #define SLAP_CTRL_UPDATE \
34 (SLAP_CTRL_ADD|SLAP_CTRL_DELETE|SLAP_CTRL_MODIFY|SLAP_CTRL_RENAME)
35 #define SLAP_CTRL_ACCESS (SLAP_CTRL_INTROGATE|SLAP_CTRL_UPDATE)
37 typedef int (SLAP_CTRL_PARSE_FN) LDAP_P((
43 static SLAP_CTRL_PARSE_FN parseManageDSAit;
44 static SLAP_CTRL_PARSE_FN parseSubentries;
46 static struct slap_control {
49 char **sc_extendedops;
50 SLAP_CTRL_PARSE_FN *sc_parse;
52 } supportedControls[] = {
53 { LDAP_CONTROL_MANAGEDSAIT,
54 SLAP_CTRL_ACCESS, NULL,
56 { LDAP_CONTROL_SUBENTRIES,
57 SLAP_CTRL_SEARCH, NULL,
63 get_supported_ctrl(int index)
65 return supportedControls[index].sc_oid;
68 static struct slap_control *
69 find_ctrl( const char *oid )
72 for( i=0; supportedControls[i].sc_oid; i++ ) {
73 if( strcmp( oid, supportedControls[i].sc_oid ) == 0 ) {
74 return &supportedControls[i];
89 BerElement *ber = op->o_ber;
90 LDAPControl ***ctrls = &op->o_ctrls;
91 struct slap_control *c;
92 int rc = LDAP_SUCCESS;
93 const char *errmsg = NULL;
95 len = ber_pvt_ber_remaining(ber);
103 if(( tag = ber_peek_tag( ber, &len )) != LDAP_TAG_CONTROLS ) {
104 if( tag == LBER_ERROR ) {
105 rc = SLAPD_DISCONNECT;
106 errmsg = "unexpected data in PDU";
113 LDAP_LOG(( "operation", LDAP_LEVEL_ENTRY,
114 "get_ctrls: conn %d\n", conn->c_connid ));
116 Debug( LDAP_DEBUG_TRACE, "=> get_ctrls\n", 0, 0, 0 );
118 if( op->o_protocol < LDAP_VERSION3 ) {
119 rc = SLAPD_DISCONNECT;
120 errmsg = "controls require LDAPv3";
124 /* set through each element */
125 *ctrls = ch_malloc( 1 * sizeof(LDAPControl *) );
128 if( *ctrls == NULL ) {
130 errmsg = "no memory";
135 *ctrls[nctrls] = NULL;
137 for( tag = ber_first_element( ber, &len, &opaque );
139 tag = ber_next_element( ber, &len, opaque ) )
142 LDAPControl **tctrls;
144 tctrl = ch_calloc( 1, sizeof(LDAPControl) );
145 tctrl->ldctl_oid = NULL;
146 tctrl->ldctl_value.bv_val = NULL;
148 /* allocate pointer space for current controls (nctrls)
149 * + this control + extra NULL
151 tctrls = (tctrl == NULL) ? NULL :
152 ch_realloc(*ctrls, (nctrls+2) * sizeof(LDAPControl *));
155 if( tctrls == NULL ) {
156 /* one of the above allocation failed */
158 if( tctrl != NULL ) {
162 ldap_controls_free(*ctrls);
166 errmsg = "no memory";
171 tctrls[nctrls++] = tctrl;
172 tctrls[nctrls] = NULL;
174 tag = ber_scanf( ber, "{a" /*}*/, &tctrl->ldctl_oid );
176 if( tag == LBER_ERROR ) {
178 LDAP_LOG(( "operation", LDAP_LEVEL_INFO,
179 "get_ctrls: conn %d get OID failed.\n",
182 Debug( LDAP_DEBUG_TRACE, "=> get_ctrls: get oid failed.\n",
186 ldap_controls_free( tctrls );
187 rc = SLAPD_DISCONNECT;
188 errmsg = "decoding controls error";
192 tag = ber_peek_tag( ber, &len );
194 if( tag == LBER_BOOLEAN ) {
196 tag = ber_scanf( ber, "b", &crit );
198 if( tag == LBER_ERROR ) {
200 LDAP_LOG(( "operation", LDAP_LEVEL_INFO,
201 "get_ctrls: conn %d get crit failed.\n",
204 Debug( LDAP_DEBUG_TRACE, "=> get_ctrls: get crit failed.\n",
208 ldap_controls_free( tctrls );
209 rc = SLAPD_DISCONNECT;
210 errmsg = "decoding controls error";
214 tctrl->ldctl_iscritical = (crit != 0);
215 tag = ber_peek_tag( ber, &len );
219 LDAP_LOG(( "operation", LDAP_LEVEL_INFO,
220 "get_ctrls: conn %d oid=\"%s\" (%scritical)\n",
221 conn->c_connid, tctrl->ldctl_oid,
222 tctrl->ldctl_iscritical ? "" : "non" ));
224 Debug( LDAP_DEBUG_TRACE, "=> get_ctrls: oid=\"%s\" (%scritical)\n",
226 tctrl->ldctl_iscritical ? "" : "non",
229 if( tag == LBER_OCTETSTRING ) {
230 tag = ber_scanf( ber, "o", &tctrl->ldctl_value );
232 if( tag == LBER_ERROR ) {
234 LDAP_LOG(( "operation", LDAP_LEVEL_INFO,
235 "get_ctrls: conn %d get value failed.\n", conn->c_connid ));
237 Debug( LDAP_DEBUG_TRACE, "=> get_ctrls: get value failed.\n",
241 ldap_controls_free( tctrls );
242 rc = SLAPD_DISCONNECT;
243 errmsg = "decoding controls error";
248 c = find_ctrl( tctrl->ldctl_oid );
250 /* recongized control */
252 switch( op->o_tag ) {
254 tagmask = SLAP_CTRL_ADD;
257 tagmask = SLAP_CTRL_BIND;
259 case LDAP_REQ_COMPARE:
260 tagmask = SLAP_CTRL_COMPARE;
262 case LDAP_REQ_DELETE:
263 tagmask = SLAP_CTRL_DELETE;
265 case LDAP_REQ_MODIFY:
266 tagmask = SLAP_CTRL_MODIFY;
268 case LDAP_REQ_RENAME:
269 tagmask = SLAP_CTRL_RENAME;
271 case LDAP_REQ_SEARCH:
272 tagmask = SLAP_CTRL_SEARCH;
274 case LDAP_REQ_UNBIND:
275 tagmask = SLAP_CTRL_UNBIND;
277 case LDAP_REQ_EXTENDED:
278 /* FIXME: check list of extended operations */
283 errmsg = "controls internal error";
287 if (( c->sc_ops_mask & tagmask ) == tagmask ) {
288 /* available extension */
292 errmsg = "not yet implemented";
296 rc = c->sc_parse( conn, op, tctrl, &errmsg );
298 if( rc != LDAP_SUCCESS ) goto return_results;
300 } else if( tctrl->ldctl_iscritical ) {
301 /* unavailable CRITICAL control */
302 rc = LDAP_UNAVAILABLE_CRITICAL_EXTENSION;
303 errmsg = "critical extension is unavailable";
307 } else if( tctrl->ldctl_iscritical ) {
308 /* unrecongized CRITICAL control */
309 rc = LDAP_UNAVAILABLE_CRITICAL_EXTENSION;
310 errmsg = "critical extension is not recongized";
319 LDAP_LOG(( "operation", LDAP_LEVEL_RESULTS,
320 "get_ctrls: conn %d %d %d %s\n",
321 conn->c_connid, nctrls, rc, errmsg ? errmsg : "" ));
323 Debug( LDAP_DEBUG_TRACE, "<= get_ctrls: %d %d %s\n",
324 nctrls, rc, errmsg ? errmsg : "");
327 if( sendres && rc != LDAP_SUCCESS ) {
328 if( rc == SLAPD_DISCONNECT ) {
329 send_ldap_disconnect( conn, op, LDAP_PROTOCOL_ERROR, errmsg );
331 send_ldap_result( conn, op, rc,
332 NULL, errmsg, NULL, NULL );
339 static int parseManageDSAit (
345 if ( op->o_managedsait != SLAP_NO_CONTROL ) {
346 *text = "manageDSAit control specified multiple times";
347 return LDAP_PROTOCOL_ERROR;
350 if ( ctrl->ldctl_value.bv_len ) {
351 *text = "manageDSAit control value not empty";
352 return LDAP_PROTOCOL_ERROR;
355 op->o_managedsait = ctrl->ldctl_iscritical
356 ? SLAP_CRITICAL_CONTROL
357 : SLAP_NONCRITICAL_CONTROL;
362 static int parseSubentries (
368 if ( op->o_subentries != SLAP_NO_CONTROL ) {
369 *text = "subentries control specified multiple times";
370 return LDAP_PROTOCOL_ERROR;
373 /* FIXME: should use BER library */
374 if( ( ctrl->ldctl_value.bv_len != 3 )
375 && ( ctrl->ldctl_value.bv_val[0] != 0x01 )
376 && ( ctrl->ldctl_value.bv_val[1] != 0x01 ))
378 *text = "subentries control value encoding is bogus";
379 return LDAP_PROTOCOL_ERROR;
382 op->o_subentries = ctrl->ldctl_iscritical
383 ? SLAP_CRITICAL_CONTROL
384 : SLAP_NONCRITICAL_CONTROL;
386 op->o_subentries_visibility = (ctrl->ldctl_value.bv_val[2] != 0x00);